当前提交
3f3df3ea63
共有 18 个文件被更改,包括 1219 次插入 和 12 次删除
|
|
@ -0,0 +1,71 @@
|
|||
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
class Bandmap extends CI_Controller {
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
$this->load->model('user_model');
|
||||
if(!$this->user_model->authorize(2)) { $this->session->set_flashdata('notice', 'You\'re not allowed to do that!'); redirect('dashboard'); }
|
||||
$this->load->model('bands');
|
||||
}
|
||||
|
||||
function index() {
|
||||
$this->load->model('cat');
|
||||
$this->load->model('bands');
|
||||
$data['radios'] = $this->cat->radios();
|
||||
$data['bands'] = $this->bands->get_user_bands_for_qso_entry();
|
||||
|
||||
$footerData = [];
|
||||
$footerData['scripts'] = [
|
||||
'assets/js/sections/bandmap.js',
|
||||
];
|
||||
|
||||
$data['page_title'] = "DXCluster";
|
||||
$this->load->view('interface_assets/header', $data);
|
||||
$this->load->view('bandmap/index');
|
||||
$this->load->view('interface_assets/footer', $footerData);
|
||||
}
|
||||
|
||||
function list() {
|
||||
$this->load->model('cat');
|
||||
$this->load->model('bands');
|
||||
$data['radios'] = $this->cat->radios();
|
||||
$data['bands'] = $this->bands->get_user_bands_for_qso_entry();
|
||||
|
||||
$footerData = [];
|
||||
$footerData['scripts'] = [
|
||||
'assets/js/moment.min.js',
|
||||
'assets/js/datetime-moment.js',
|
||||
'assets/js/sections/bandmap_list.js'
|
||||
];
|
||||
|
||||
$CI =& get_instance();
|
||||
// Get Date format
|
||||
if($CI->session->userdata('user_date_format')) {
|
||||
// If Logged in and session exists
|
||||
$pageData['custom_date_format'] = $CI->session->userdata('user_date_format');
|
||||
} else {
|
||||
// Get Default date format from /config/cloudlog.php
|
||||
$pageData['custom_date_format'] = $CI->config->item('qso_date_format');
|
||||
}
|
||||
|
||||
switch ($pageData['custom_date_format']) {
|
||||
case "d/m/y": $pageData['custom_date_format'] = 'DD/MM/YY'; break;
|
||||
case "d/m/Y": $pageData['custom_date_format'] = 'DD/MM/YYYY'; break;
|
||||
case "m/d/y": $pageData['custom_date_format'] = 'MM/DD/YY'; break;
|
||||
case "m/d/Y": $pageData['custom_date_format'] = 'MM/DD/YYYY'; break;
|
||||
case "d.m.Y": $pageData['custom_date_format'] = 'DD.MM.YYYY'; break;
|
||||
case "y/m/d": $pageData['custom_date_format'] = 'YY/MM/DD'; break;
|
||||
case "Y-m-d": $pageData['custom_date_format'] = 'YYYY-MM-DD'; break;
|
||||
case "M d, Y": $pageData['custom_date_format'] = 'MMM DD, YYYY'; break;
|
||||
case "M d, y": $pageData['custom_date_format'] = 'MMM DD, YY'; break;
|
||||
default: $pageData['custom_date_format'] = 'DD/MM/YYYY';
|
||||
}
|
||||
|
||||
$data['page_title'] = "DXCluster";
|
||||
$this->load->view('interface_assets/header', $data);
|
||||
$this->load->view('bandmap/list',$pageData);
|
||||
$this->load->view('interface_assets/footer', $footerData);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
class Dxcluster extends CI_Controller {
|
||||
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->load->model('user_model');
|
||||
if(!$this->user_model->authorize(2)) { $this->session->set_flashdata('notice', 'You\'re not allowed to do that!'); redirect('dashboard'); }
|
||||
$this->load->model('dxcluster_model');
|
||||
}
|
||||
|
||||
|
||||
function spots($band,$age = '', $de = '') {
|
||||
if ($age == '') {
|
||||
$age = $this->optionslib->get_option('dxcluster_maxage');
|
||||
}
|
||||
if ($de == '') {
|
||||
$de = $this->optionslib->get_option('dxcluster_decont');
|
||||
}
|
||||
$calls_found=$this->dxcluster_model->dxc_spotlist($band, $age, $de);
|
||||
header('Content-Type: application/json');
|
||||
if ($calls_found) {
|
||||
echo json_encode($calls_found, JSON_PRETTY_PRINT);
|
||||
} else {
|
||||
echo '{ "error": "not found" }';
|
||||
}
|
||||
}
|
||||
|
||||
function qrg_lookup($qrg) {
|
||||
$call_found=$this->dxcluster_model->dxc_qrg_lookup($this->security->xss_clean($qrg));
|
||||
header('Content-Type: application/json');
|
||||
if ($call_found) {
|
||||
echo json_encode($call_found, JSON_PRETTY_PRINT);
|
||||
} else {
|
||||
echo '{ "error": "not found" }';
|
||||
}
|
||||
}
|
||||
|
||||
function call($call) {
|
||||
$this->load->model('logbook_model');
|
||||
|
||||
$date = date('Ymd', time());
|
||||
$dxcc = $this->logbook_model->dxcc_lookup($call, $date);
|
||||
|
||||
if ($dxcc) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode($dxcc, JSON_PRETTY_PRINT);
|
||||
} else {
|
||||
echo '{ "error": "not found" }';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -159,12 +159,24 @@ class Options extends CI_Controller {
|
|||
$this->load->library('form_validation');
|
||||
|
||||
$this->form_validation->set_rules('dxcache_url', 'URL of DXCache', 'valid_url');
|
||||
$this->form_validation->set_rules('dxcluster_maxage', 'Max Age of Spots', 'required');
|
||||
$this->form_validation->set_rules('dxcluster_decont', 'de continent', 'required');
|
||||
|
||||
if ($this->form_validation->run() == FALSE) {
|
||||
$this->load->view('interface_assets/header', $data);
|
||||
$this->load->view('options/dxcluster');
|
||||
$this->load->view('interface_assets/footer');
|
||||
} else {
|
||||
$dxcluster_decont_update = $this->optionslib->update('dxcluster_decont', $this->input->post('dxcluster_decont'), 'yes');
|
||||
if($dxcluster_decont_update == TRUE) {
|
||||
$this->session->set_flashdata('success', $this->lang->line('options_dxcluster_decont_changed_to').$this->input->post('dxcluster_decont'));
|
||||
}
|
||||
|
||||
$dxcluster_maxage_update = $this->optionslib->update('dxcluster_maxage', $this->input->post('dxcluster_maxage'), 'yes');
|
||||
if($dxcluster_maxage_update == TRUE) {
|
||||
$this->session->set_flashdata('success', $this->lang->line('options_dxcluster_maxage_changed_to').$this->input->post('dxcluster_maxage'));
|
||||
}
|
||||
|
||||
$dxcache_url_update = $this->optionslib->update('dxcache_url', $this->input->post('dxcache_url'), 'yes');
|
||||
if($dxcache_url_update == TRUE) {
|
||||
$this->session->set_flashdata('success', $this->lang->line('options_dxcache_url_changed_to').$this->input->post('dxcache_url'));
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ $lang['menu_live_qso'] = 'Live QSO';
|
|||
$lang['menu_post_qso'] = 'Post QSO';
|
||||
$lang['menu_live_contest_logging'] = 'Live Contest Logging';
|
||||
$lang['menu_post_contest_logging'] = 'Post Contest Logging';
|
||||
$lang['menu_bandmap'] = 'Bandmap';
|
||||
$lang['menu_view_qsl'] = 'View QSL';
|
||||
$lang['menu_view_eqsl'] = 'View eQSL';
|
||||
|
||||
|
|
|
|||
|
|
@ -64,5 +64,10 @@ $lang['options_dxcluster_longtext'] = 'The Provider of the DXCluster-Cache. You
|
|||
$lang['options_dxcluster_hint'] = 'URL of the DXCluster-Cache. e.g. https://dxc.jo30.de/dxcache';
|
||||
$lang['options_dxcluster_settings'] = 'DXCluster';
|
||||
$lang['options_dxcache_url_changed_to'] = 'DXCluster Cache URL changed to ';
|
||||
$lang['options_dxcluster_maxage'] = 'Maximum Age of spots taken care of';
|
||||
$lang['options_dxcluster_maxage_hint'] = 'The Age in Minutes of spots, that will be taken care at bandplan/lookup';
|
||||
$lang['options_dxcluster_decont'] = 'Show spots which are spotted from following continent';
|
||||
$lang['options_dxcluster_maxage_changed_to']='Maximum age of spots changed to ';
|
||||
$lang['options_dxcluster_decont_changed_to']='de continent changed to ';
|
||||
|
||||
$lang['options_save'] = 'Save';
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ $lang['menu_live_qso'] = 'Live QSO';
|
|||
$lang['menu_post_qso'] = 'Zeitversetztes QSO';
|
||||
$lang['menu_live_contest_logging'] = 'Live Contest Logging';
|
||||
$lang['menu_post_contest_logging'] = 'Zeitversetztes Contest Logging';
|
||||
$lang['menu_bandmap'] = 'Bandmap';
|
||||
$lang['menu_view_qsl'] = 'QSL Ansicht';
|
||||
$lang['menu_view_eqsl'] = 'eQSL Ansicht';
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,9 @@ $lang['options_dxcluster_longtext'] = 'Der Provider des DXCluster-Caches. Du kan
|
|||
$lang['options_dxcluster_hint'] = 'URL des DXCluster-Caches. z.B. https://dxc.jo30.de/dxcache';
|
||||
$lang['options_dxcluster_settings'] = 'DXCluster';
|
||||
$lang['options_dxcache_url_changed_to'] = 'DXCluster Cache URL geänder zu ';
|
||||
|
||||
$lang['options_dxcluster_maxage'] = 'Maximales Alter bis zu dem Spots berücksichtigt werden';
|
||||
$lang['options_dxcluster_decont'] = 'Nur Spots berücksichtigen, die in folgendem Kontinent erfasst wurden';
|
||||
$lang['options_dxcluster_maxage_changed_to']='Maximal Spot-Alter geänder auf ';
|
||||
$lang['options_dxcluster_decont_changed_to']='Spotterkontinent geändert auf ';
|
||||
|
||||
$lang['options_save'] = 'Speichern';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,119 @@
|
|||
<?php
|
||||
|
||||
use Cloudlog\Dxcc\Dxcc;
|
||||
|
||||
class Dxcluster_model extends CI_Model {
|
||||
public function dxc_spotlist($band = '20m', $maxage = 60, $de = '') {
|
||||
$this->load->helper(array('psr4_autoloader'));
|
||||
$CI =& get_instance();
|
||||
if ( ($this->optionslib->get_option('dxcache_url') != '') ) {
|
||||
if($CI->session->userdata('user_date_format')) {
|
||||
$custom_date_format = $CI->session->userdata('user_date_format');
|
||||
} else {
|
||||
$custom_date_format = $CI->config->item('qso_date_format');
|
||||
}
|
||||
|
||||
$dxcache_url = $this->optionslib->get_option('dxcache_url').'/spots/'.$band;
|
||||
$CI->load->model('logbooks_model');
|
||||
$CI->load->model('logbook_model');
|
||||
$logbooks_locations_array = $CI->logbooks_model->list_logbook_relationships($this->session->userdata('active_station_logbook'));
|
||||
|
||||
// CURL Functions
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $dxcache_url);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, 'Cloudlog DXLookup');
|
||||
curl_setopt($ch, CURLOPT_HEADER, false);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$jsonraw = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
$json = json_decode($jsonraw);
|
||||
$date = date('Ymd', time());
|
||||
|
||||
$dxccObj = new DXCC($date);
|
||||
|
||||
// Create JSON object
|
||||
if (strlen($jsonraw)>20) {
|
||||
$spotsout=[];
|
||||
foreach($json as $singlespot){
|
||||
$spotband = $CI->frequency->GetBand($singlespot->frequency*1000);
|
||||
$singlespot->band=$spotband;
|
||||
if ($band != $spotband) { continue; }
|
||||
$datetimecurrent = new DateTime("now", new DateTimeZone('UTC')); // Today's Date/Time
|
||||
$datetimespot = new DateTime($singlespot->when, new DateTimeZone('UTC'));
|
||||
$spotage = $datetimecurrent->diff($datetimespot);
|
||||
$minutes = $spotage->days * 24 * 60;
|
||||
$minutes += $spotage->h * 60;
|
||||
$minutes += $spotage->i;
|
||||
$singlespot->age=$minutes;
|
||||
$singlespot->when_pretty=date($custom_date_format . " H:i", strtotime($singlespot->when));
|
||||
|
||||
if ($minutes<=$maxage) {
|
||||
if (!(property_exists($singlespot,'dxcc_spotted'))) { // Check if we already have dxcc of spotted
|
||||
$dxcc=$dxccObj->dxcc_lookup($singlespot->spotted,date('Ymd', time()));
|
||||
$singlespot->dxcc_spotted=$dxcc;
|
||||
}
|
||||
if (!(property_exists($singlespot,'dxcc_spotter'))) { // Check if we already have dxcc of spotter
|
||||
$dxcc=$dxccObj->dxcc_lookup($singlespot->spotter,date('Ymd', time()));
|
||||
$singlespot->dxcc_spotter=$dxcc;
|
||||
}
|
||||
if ( ($de != '') && ($de != 'Any') && (property_exists($singlespot->dxcc_spotter,'cont')) ){ // If we have a "de continent" and a filter-wish filter on that
|
||||
if (strtolower($de) == strtolower($singlespot->dxcc_spotter->cont)) {
|
||||
$singlespot->worked_call = ($this->logbook_model->check_if_callsign_worked_in_logbook($singlespot->spotted, $logbooks_locations_array, $singlespot->band) == 1);
|
||||
array_push($spotsout,$singlespot);
|
||||
}
|
||||
} else { // No de continent? No Filter --> Just push
|
||||
$singlespot->worked_call = ($this->logbook_model->check_if_callsign_worked_in_logbook($singlespot->spotted, $logbooks_locations_array, $singlespot->band) == 1);
|
||||
array_push($spotsout,$singlespot);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ($spotsout);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
public function dxc_qrg_lookup($qrg, $maxage = 120) {
|
||||
$this->load->helper(array('psr4_autoloader'));
|
||||
if ( ($this->optionslib->get_option('dxcache_url') != '') && (is_numeric($qrg)) ) {
|
||||
$dxcache_url = $this->optionslib->get_option('dxcache_url').'/spot/'.$qrg;
|
||||
|
||||
// CURL Functions
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $dxcache_url);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, 'Cloudlog DXLookup by QRG');
|
||||
curl_setopt($ch, CURLOPT_HEADER, false);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$jsonraw = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
$json = json_decode($jsonraw);
|
||||
|
||||
$date = date('Ymd', time());
|
||||
|
||||
$dxccObj = new DXCC($date);
|
||||
|
||||
// Create JSON object
|
||||
if (strlen($jsonraw)>20) {
|
||||
$datetimecurrent = new DateTime("now", new DateTimeZone('UTC')); // Today's Date/Time
|
||||
$datetimespot = new DateTime($json->when, new DateTimeZone('UTC'));
|
||||
$spotage = $datetimecurrent->diff($datetimespot);
|
||||
$minutes = $spotage->days * 24 * 60;
|
||||
$minutes += $spotage->h * 60;
|
||||
$minutes += $spotage->i;
|
||||
$json->age=$minutes;
|
||||
if ($minutes<=$maxage) {
|
||||
$dxcc=$dxccObj->dxcc_lookup($json->spotter,date('Ymd', time()));
|
||||
$json->dxcc_spotter=$dxcc;
|
||||
return ($json);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -640,7 +640,7 @@ class Logbook_model extends CI_Model {
|
|||
if ($replaceoption) {
|
||||
$post_data['Cmd'] = 'UPDATE';
|
||||
$post_data['ADIFKey'] = $adif;
|
||||
}
|
||||
}
|
||||
$post_data['ADIFData'] = $adif;
|
||||
|
||||
$post_data['Callsign'] = $station_callsign;
|
||||
|
|
@ -2755,7 +2755,7 @@ class Logbook_model extends CI_Model {
|
|||
|
||||
if (($station_id != 0) && ($record['station_callsign'] != $station_profile_call)) { // Check if station_call from import matches profile ONLY when submitting via GUI.
|
||||
return "Wrong station_callsign ".$record['station_callsign']." while importing QSO with ".$record['call']." for ".$station_profile_call." : SKIPPED";
|
||||
}
|
||||
}
|
||||
|
||||
$CI =& get_instance();
|
||||
$CI->load->library('frequency');
|
||||
|
|
@ -3992,7 +3992,6 @@ class Logbook_model extends CI_Model {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function validateADIFDate($date, $format = 'Ymd')
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
<script>
|
||||
var dxcluster_provider="<?php echo base_url(); ?>index.php/dxcluster";
|
||||
var dxcluster_maxage=<?php echo $this->optionslib->get_option('dxcluster_maxage'); ?>;
|
||||
var cat_timeout_interval="<?php echo $this->optionslib->get_option('cat_timeout_interval'); ?>";
|
||||
</script>
|
||||
|
||||
|
||||
<div class="container">
|
||||
<br>
|
||||
<center><button type="button" class="btn" id="menutoggle"><i class="fa fa-arrow-up" id="menutoggle_i"></i></button></center>
|
||||
<h2 id="dxtitle"><?php echo $page_title; ?></h2>
|
||||
<div class="tabs" id="dxtabs">
|
||||
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="index">BandMap</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="list">BandList</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tab-content" id="myTabContent">
|
||||
<div class="messages my-1 mr-2"></div>
|
||||
<div class="form-inline">
|
||||
<label class="my-1 mr-2" for="radio"><?php echo lang('gen_hamradio_radio'); ?></label>
|
||||
<select class="form-control-sm radios my-1 mr-sm-2" id="radio" name="radio">
|
||||
<option value="0" selected="selected"><?php echo lang('general_word_none'); ?></option>
|
||||
<?php foreach ($radios->result() as $row) { ?>
|
||||
<option value="<?php echo $row->id; ?>" <?php if($this->session->userdata('radio') == $row->id) { echo "selected=\"selected\""; } ?>><?php echo $row->radio; ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
|
||||
<label class="my-1 mr-2" for="decontSelect">Spots de</label>
|
||||
<select class="form-control-sm my-1 mr-sm-2" id="decontSelect" name="dxcluster_decont" aria-describedby="dxcluster_decontHelp" required>
|
||||
<option value="Any">*</option>
|
||||
<option value="AF"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'AF') { echo " selected"; } ?>>Africa</option>
|
||||
<option value="AN"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'AN') { echo " selected"; } ?>>Antarctica</option>
|
||||
<option value="AS"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'AS') { echo " selected"; } ?>>Asia</option>
|
||||
<option value="EU"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'EU') { echo " selected"; } ?>>Europe</option>
|
||||
<option value="NA"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'NA') { echo " selected"; } ?>>North America</option>
|
||||
<option value="OC"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'OC') { echo " selected"; } ?>>Oceania</option>
|
||||
<option value="SA"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'SA') { echo " selected"; } ?>>South America</option>
|
||||
</select>
|
||||
|
||||
<label class="my-1 mr-2" for="band"><?php echo lang('gen_hamradio_band'); ?></label>
|
||||
<select id="band" class="form-control-sm my-1 mr-sm-2" name="band">
|
||||
<?php foreach($bands as $key=>$bandgroup) {
|
||||
echo '<optgroup label="' . strtoupper($key) . '">';
|
||||
foreach($bandgroup as $band) {
|
||||
echo '<option value="' . $band . '"';
|
||||
if ($band == "20m") echo ' selected';
|
||||
echo '>' . $band . '</option>'."\n";
|
||||
}
|
||||
echo '</optgroup>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<figure class="highcharts-figure">
|
||||
<div id="bandmap"></div>
|
||||
<p class="highcharts-description">
|
||||
</p>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
<script>
|
||||
var dxcluster_provider="<?php echo base_url(); ?>index.php/dxcluster";
|
||||
var cat_timeout_interval="<?php echo $this->optionslib->get_option('cat_timeout_interval'); ?>";
|
||||
var dxcluster_maxage=<?php echo $this->optionslib->get_option('dxcluster_maxage'); ?>;
|
||||
var custom_date_format = "<?php echo $custom_date_format ?>";
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.fresh{
|
||||
-webkit-transition: all 15s ease;
|
||||
-moz-transition: all 15s ease;
|
||||
-o-transition: all 15s ease;
|
||||
transition: all 15s ease;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<div class="container">
|
||||
<br>
|
||||
<center><button type="button" class="btn" id="menutoggle"><i class="fa fa-arrow-up" id="menutoggle_i"></i></button></center>
|
||||
|
||||
<h2 id="dxtitle"><?php echo $page_title; ?></h2>
|
||||
|
||||
<div id="dxtabs" class="tabs">
|
||||
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="index">BandMap</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="list">BandList</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="tab-content" id="myTabContent">
|
||||
<div class="messages my-1 mr-2"></div>
|
||||
<div class="form-inline">
|
||||
<label class="my-1 mr-2" for="radio"><?php echo lang('gen_hamradio_radio'); ?></label>
|
||||
<select class="form-control-sm radios my-1 mr-sm-2" id="radio" name="radio">
|
||||
<option value="0" selected="selected"><?php echo lang('general_word_none'); ?></option>
|
||||
<?php foreach ($radios->result() as $row) { ?>
|
||||
<option value="<?php echo $row->id; ?>" <?php if($this->session->userdata('radio') == $row->id) { echo "selected=\"selected\""; } ?>><?php echo $row->radio; ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
<label class="my-1 mr-2" for="decontSelect">Spots de</label>
|
||||
<select class="form-control-sm my-1 mr-sm-2" id="decontSelect" name="dxcluster_decont" aria-describedby="dxcluster_decontHelp" required>
|
||||
<option value="Any">*</option>
|
||||
<option value="AF"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'AF') { echo " selected"; } ?>>Africa</option>
|
||||
<option value="AN"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'AN') { echo " selected"; } ?>>Antarctica</option>
|
||||
<option value="AS"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'AS') { echo " selected"; } ?>>Asia</option>
|
||||
<option value="EU"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'EU') { echo " selected"; } ?>>Europe</option>
|
||||
<option value="NA"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'NA') { echo " selected"; } ?>>North America</option>
|
||||
<option value="OC"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'OC') { echo " selected"; } ?>>Oceania</option>
|
||||
<option value="SA"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'SA') { echo " selected"; } ?>>South America</option>
|
||||
</select>
|
||||
|
||||
<label class="my-1 mr-2" for="band"><?php echo lang('gen_hamradio_band'); ?></label>
|
||||
<select id="band" class="form-control-sm my-1 mr-sm-2" name="band">
|
||||
<?php foreach($bands as $key=>$bandgroup) {
|
||||
echo '<optgroup label="' . strtoupper($key) . '">';
|
||||
foreach($bandgroup as $band) {
|
||||
echo '<option value="' . $band . '"';
|
||||
if ($band == "20m") echo ' selected';
|
||||
echo '>' . $band . '</option>'."\n";
|
||||
}
|
||||
echo '</optgroup>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
|
||||
<table style="width:100%" class="table-sm table spottable table-bordered table-hover table-striped table-condensed">
|
||||
<thead>
|
||||
<tr class="log_title titles">
|
||||
<th><?php echo lang('general_word_date'); ?>/<?php echo lang('general_word_time'); ?></th>
|
||||
<th><?php echo lang('gen_hamradio_frequency'); ?></th>
|
||||
<th><?php echo lang('gen_hamradio_call'); ?></th>
|
||||
<th>DXCC</th>
|
||||
<th><?php echo lang('gen_hamradio_call'); ?> Spotter</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody class="spots_table_contents">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -937,10 +937,10 @@ $(document).on('keypress',function(e) {
|
|||
|
||||
if ($this->optionslib->get_option('dxcache_url') != ''){ ?>
|
||||
<script type="text/javascript">
|
||||
var dxcluster_provider =' <?php echo $this->optionslib->get_option('dxcache_url'); ?>';
|
||||
var dxcluster_provider = '<?php echo base_url(); ?>index.php/dxcluster';
|
||||
$(document).ready(function() {
|
||||
$("#check_cluster").on("click", function() {
|
||||
$.ajax({ url: dxcluster_provider+"/spot/"+$("#frequency").val()/1000, cache: false, dataType: "json" }).done(
|
||||
$.ajax({ url: dxcluster_provider+"/qrg_lookup/"+$("#frequency").val()/1000, cache: false, dataType: "json" }).done(
|
||||
function(dxspot) {
|
||||
$("#callsign").val(dxspot.spotted);
|
||||
$("#callsign").trigger("blur");
|
||||
|
|
@ -2911,6 +2911,15 @@ function viewEqsl(picture, callsign) {
|
|||
</script>
|
||||
<?php } ?>
|
||||
|
||||
<?php if ($this->uri->segment(1) == "bandmap") { ?>
|
||||
|
||||
<script src="https://code.highcharts.com/highcharts.js"></script>
|
||||
<script src="https://code.highcharts.com/modules/timeline.js"></script>
|
||||
<script src="https://code.highcharts.com/modules/exporting.js"></script>
|
||||
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
<?php if ($this->uri->segment(1) == "awards") {
|
||||
// Get Date format
|
||||
if($this->session->userdata('user_date_format')) {
|
||||
|
|
|
|||
|
|
@ -80,6 +80,10 @@
|
|||
<a class="dropdown-item" href="<?php echo site_url('contesting?manual=0');?>" title="Live contest QSOs"><i class="fas fa-list"></i> <?php echo lang('menu_live_contest_logging'); ?></a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="<?php echo site_url('contesting?manual=1');?>" title="Post contest QSOs"><i class="fas fa-list"></i> <?php echo lang('menu_post_contest_logging'); ?></a>
|
||||
<?php if ($this->optionslib->get_option('dxcache_url') != '') { ?>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="<?php echo site_url('bandmap/index');?>" title="Bandmap"><i class="fa fa-id-card"></i> <?php echo lang('menu_bandmap'); ?></a>
|
||||
<?php } ?>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="<?php echo site_url('qsl');?>" title="QSL"><i class="fa fa-id-card"></i> <?php echo lang('menu_view_qsl'); ?></a>
|
||||
<div class="dropdown-divider"></div>
|
||||
|
|
@ -179,7 +183,7 @@
|
|||
<div class="dropdown-divider"></div>
|
||||
|
||||
<a class="dropdown-item" href="<?php echo site_url('debug');?>" title="Debug Information"><i class="fas fa-tools"></i> <?php echo lang('menu_debug_information'); ?></a>
|
||||
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<?php } ?>
|
||||
|
|
@ -282,8 +286,8 @@ $oqrs_requests = $CI->oqrs_model->oqrs_requests($location_list);
|
|||
<a class="dropdown-item" href="<?php echo site_url('user/logout');?>" title="Logout"><i class="fas fa-sign-out-alt"></i> <?php echo lang('menu_logout'); ?></a>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<?php
|
||||
|
||||
<?php
|
||||
// Can add extra menu items by defining them in options. The format is json.
|
||||
// Useful to add extra things in Cloudlog without the need for modifying files. If you add extras, these files will not be overwritten when updating.
|
||||
//
|
||||
|
|
@ -308,7 +312,7 @@ $oqrs_requests = $CI->oqrs_model->oqrs_requests($location_list);
|
|||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Extras</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<?php
|
||||
<?php
|
||||
foreach(json_decode($this->optionslib->get_option('menuitems')) as $item) {
|
||||
echo '<a class="dropdown-item" href="' . site_url($item->url) . '" title="Gridsquares"><i class="fas '. $item->icon .'"></i> ' . $item->text . '</a>';
|
||||
}
|
||||
|
|
@ -316,7 +320,7 @@ $oqrs_requests = $CI->oqrs_model->oqrs_requests($location_list);
|
|||
</div>
|
||||
</li>
|
||||
<?php } ?>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
<?php } ?>
|
||||
|
|
|
|||
|
|
@ -40,7 +40,29 @@
|
|||
<input type="text" name="dxcache_url" class="form-control" id="dxcache_url" aria-describedby="dxcache_urlHelp" value="<?php echo $this->optionslib->get_option('dxcache_url'); ?>">
|
||||
<small id="dxcache_urlHelp" class="form-text text-muted"><?php echo lang('options_dxcluster_hint'); ?></small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="maxAgeSelect"><?php echo lang('options_dxcluster_maxage'); ?></label>
|
||||
<select class="custom-select" id="maxAgeSelect" name="dxcluster_maxage" aria-describedby="dxcluster_maxageHelp" required>
|
||||
<option value="120"<?php if ($this->optionslib->get_option('dxcluster_maxage') == '120') { echo " selected"; } ?>>2 Hours</option>
|
||||
<option value="60"<?php if ($this->optionslib->get_option('dxcluster_maxage') == '60') { echo " selected"; } ?>>60 Minutes</option>
|
||||
<option value="30"<?php if ($this->optionslib->get_option('dxcluster_maxage') == '30') { echo " selected"; } ?>>30 Minutes</option>
|
||||
</select>
|
||||
<small id="dxcluster_maxageHelp" class="form-text text-muted"><?php echo lang('options_dxcluster_maxage_hint'); ?></small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="decontSelect"><?php echo lang('options_dxcluster_decont'); ?></label>
|
||||
<select class="custom-select" id="decontSelect" name="dxcluster_decont" aria-describedby="dxcluster_decontHelp" required>
|
||||
<option value="AF"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'AF') { echo " selected"; } ?>>Africa</option>
|
||||
<option value="AN"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'AN') { echo " selected"; } ?>>Antarctica</option>
|
||||
<option value="AS"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'AS') { echo " selected"; } ?>>Asia</option>
|
||||
<option value="EU"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'EU') { echo " selected"; } ?>>Europe</option>
|
||||
<option value="NA"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'NA') { echo " selected"; } ?>>North America</option>
|
||||
<option value="OC"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'OC') { echo " selected"; } ?>>Oceania</option>
|
||||
<option value="SA"<?php if ($this->optionslib->get_option('dxcluster_decont') == 'SA') { echo " selected"; } ?>>South America</option>
|
||||
</select>
|
||||
<small id="dxcluster_decontHelp" class="form-text text-muted"><?php echo lang('options_dxcluster_decont_hint'); ?></small>
|
||||
</div>
|
||||
|
||||
<!-- Save the Form -->
|
||||
<input class="btn btn-primary" type="submit" value="<?php echo lang('options_save'); ?>" />
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -458,3 +458,53 @@ div#station_logbooks_linked_table_paginate {
|
|||
.lotw_info_red {
|
||||
background-image: linear-gradient(to bottom, #3fb618, red);
|
||||
}
|
||||
|
||||
|
||||
.highcharts-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.highcharts-figure,
|
||||
.highcharts-data-table table {
|
||||
min-width: 320px;
|
||||
max-width: 100%;
|
||||
margin: 1em auto;
|
||||
max-height: calc(100vh - 200px) !important;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.highcharts-data-table table {
|
||||
font-family: Verdana, sans-serif;
|
||||
border-collapse: collapse;
|
||||
border: 1px solid #ebebeb;
|
||||
margin: 10px auto;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.highcharts-data-table caption {
|
||||
padding: 1em 0;
|
||||
font-size: 1.2em;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.highcharts-data-table th {
|
||||
font-weight: 600;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.highcharts-data-table td,
|
||||
.highcharts-data-table th,
|
||||
.highcharts-data-table caption {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.highcharts-data-table thead tr,
|
||||
.highcharts-data-table tr:nth-child(even) {
|
||||
background: #f8f8f8;
|
||||
}
|
||||
|
||||
.highcharts-data-table tr:hover {
|
||||
background: #f1f7ff;
|
||||
}
|
||||
254
assets/js/sections/bandmap.js
普通文件
254
assets/js/sections/bandmap.js
普通文件
|
|
@ -0,0 +1,254 @@
|
|||
$(function() {
|
||||
(function(H) {
|
||||
H.seriesTypes.timeline.prototype.distributeDL = function() {
|
||||
var series = this,
|
||||
dataLabelsOptions = series.options.dataLabels,
|
||||
options,
|
||||
pointDLOptions,
|
||||
newOptions = {},
|
||||
visibilityIndex = 1,
|
||||
j = 2,
|
||||
distance;
|
||||
|
||||
series.points.forEach(function(point, i) {
|
||||
distance = dataLabelsOptions.distance;
|
||||
|
||||
if (point.visible && !point.isNull) {
|
||||
options = point.options;
|
||||
pointDLOptions = point.options.dataLabels;
|
||||
|
||||
if (!series.hasRendered) {
|
||||
point.userDLOptions = H.merge({}, pointDLOptions);
|
||||
}
|
||||
|
||||
/*
|
||||
if (i === j || i === j + 1) {
|
||||
distance = distance * 2.5
|
||||
|
||||
if (i === j + 1) {
|
||||
j += 4
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (i % 6 == 0) { distance = distance * 1; }
|
||||
if (i % 6 == 1) { distance = distance * -1; }
|
||||
if (i % 6 == 2) { distance = distance * 2; }
|
||||
if (i % 6 == 3) { distance = distance * -2; }
|
||||
if (i % 6 == 4) { distance = distance * 3; }
|
||||
if (i % 6 == 5) { distance = distance * -3; }
|
||||
|
||||
newOptions[series.chart.inverted ? 'x' : 'y'] = distance;
|
||||
// newOptions[series.chart.inverted ? 'x' : 'y'] = dataLabelsOptions.alternate && (visibilityIndex % 3 != 0) ? -distance : distance;
|
||||
|
||||
options.dataLabels = H.merge(newOptions, point.userDLOptions);
|
||||
visibilityIndex++;
|
||||
}
|
||||
});
|
||||
}
|
||||
}(Highcharts));
|
||||
|
||||
var bandMapChart;
|
||||
var color = ifDarkModeThemeReturn('white', 'grey');
|
||||
|
||||
function render_chart (band,spot_data) {
|
||||
let chartObject=Highcharts.chart('bandmap', {
|
||||
chart: {
|
||||
type: 'timeline',
|
||||
zoomType: 'x',
|
||||
inverted: true,
|
||||
backgroundColor: getBodyBackground(),
|
||||
height: '800px'
|
||||
},
|
||||
accessibility: {
|
||||
screenReaderSection: {
|
||||
beforeChartFormat: '<h5>{chartTitle}</h5>' +
|
||||
'<div>{typeDescription}</div>' +
|
||||
'<div>{chartSubtitle}</div>' +
|
||||
'<div>{chartLongdesc}</div>' +
|
||||
'<div>{viewTableButton}</div>'
|
||||
},
|
||||
point: {
|
||||
valueDescriptionFormat: '{index}. {point.label}. {point.description}.'
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
lineColor: color,
|
||||
visible: true,
|
||||
type: 'linear',
|
||||
labels: {
|
||||
style: {
|
||||
color: color,
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
visible: false,
|
||||
},
|
||||
title: {
|
||||
text: band,
|
||||
style: {
|
||||
color: color
|
||||
}
|
||||
},
|
||||
series: [ { data: spot_data } ]
|
||||
});
|
||||
return chartObject;
|
||||
}
|
||||
|
||||
function SortByQrg(a, b){
|
||||
var a = a.frequency;
|
||||
var b = b.frequency;
|
||||
return ((a< b) ? -1 : ((a> b) ? 1 : 0));
|
||||
}
|
||||
|
||||
function reduce_spots(spotobject) {
|
||||
let unique=[];
|
||||
spotobject.forEach((single) => {
|
||||
if (!spotobject.find((item) => ((item.spotted == single.spotted) && (item.frequency == single.frequency) && (Date.parse(item.when)>Date.parse(single.when))))) {
|
||||
unique.push(single);
|
||||
}
|
||||
});
|
||||
return unique;
|
||||
}
|
||||
|
||||
function convert2high(spotobject) {
|
||||
let ret={};
|
||||
ret.name=spotobject.spotted;
|
||||
ret.x=spotobject.frequency;
|
||||
ret.description=spotobject.frequency + " / "+Math.round( (Date.now() - Date.parse(spotobject.when)) / 1000 / 60)+"min. ago";
|
||||
ret.dataLabels={};
|
||||
ret.dataLabels.alternate=true;
|
||||
ret.dataLabels.distance=200;
|
||||
return ret;
|
||||
}
|
||||
|
||||
function update_chart(band,maxAgeMinutes) {
|
||||
if ((band != '') && (band !== undefined)) {
|
||||
let dxurl = dxcluster_provider + "/spots/" + band + "/" +maxAgeMinutes;
|
||||
$.ajax({
|
||||
url: dxurl,
|
||||
cache: false,
|
||||
dataType: "json"
|
||||
}).done(function(dxspots) {
|
||||
spots4chart=[];
|
||||
if (dxspots.length>0) {
|
||||
dxspots.sort(SortByQrg);
|
||||
dxspots=reduce_spots(dxspots);
|
||||
dxspots.forEach((single) => {
|
||||
spots4chart.push(convert2high(single));
|
||||
});
|
||||
}
|
||||
bandMapChart.title.text=band;
|
||||
bandMapChart.series[0].setData(spots4chart);
|
||||
bandMapChart.redraw();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function set_chart(band, de, maxAgeMinutes) {
|
||||
if ((band != '') && (band !== undefined)) {
|
||||
let dxurl = dxcluster_provider + "/spots/" + band + "/" +maxAgeMinutes + "/" + de;
|
||||
$.ajax({
|
||||
url: dxurl,
|
||||
cache: false,
|
||||
dataType: "json"
|
||||
}).done(function(dxspots) {
|
||||
spots4chart=[];
|
||||
if (dxspots.length>0) {
|
||||
dxspots.sort(SortByQrg);
|
||||
dxspots=reduce_spots(dxspots);
|
||||
dxspots.forEach((single) => {
|
||||
spots4chart.push(convert2high(single));
|
||||
});
|
||||
}
|
||||
bandMapChart=render_chart(band,spots4chart);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$("#menutoggle").on("click", function() {
|
||||
if ($('.navbar').is(":hidden")) {
|
||||
$('.navbar').show();
|
||||
$('#dxtabs').show();
|
||||
$('#dxtitle').show();
|
||||
$('#menutoggle_i').removeClass('fa-arrow-down');
|
||||
$('#menutoggle_i').addClass('fa-arrow-up');
|
||||
} else {
|
||||
$('.navbar').hide();
|
||||
$('#dxtabs').hide();
|
||||
$('#dxtitle').hide();
|
||||
$('#menutoggle_i').removeClass('fa-arrow-up');
|
||||
$('#menutoggle_i').addClass('fa-arrow-down');
|
||||
}
|
||||
});
|
||||
|
||||
set_chart($('#band option:selected').val(), $('#decontSelect option:selected').val(), dxcluster_maxage);
|
||||
setInterval(function () { update_chart($('#band option:selected').val(),dxcluster_maxage); },60000);
|
||||
$("#band").on("change",function() {
|
||||
set_chart($('#band option:selected').val(), $('#decontSelect option:selected').val(), dxcluster_maxage);
|
||||
});
|
||||
|
||||
$("#decontSelect").on("change",function() {
|
||||
set_chart($('#band option:selected').val(), $('#decontSelect option:selected').val(), dxcluster_maxage);
|
||||
});
|
||||
});
|
||||
|
||||
var updateFromCAT = function() {
|
||||
if($('select.radios option:selected').val() != '0') {
|
||||
radioID = $('select.radios option:selected').val();
|
||||
$.getJSON( base_url + "radio/json/" + radioID, function( data ) {
|
||||
|
||||
if (data.error) {
|
||||
if (data.error == 'not_logged_in') {
|
||||
$(".radio_cat_state" ).remove();
|
||||
if($('.radio_login_error').length == 0) {
|
||||
$('.messages').prepend('<div class="alert alert-danger radio_login_error" role="alert"><i class="fas fa-broadcast-tower"></i> You\'re not logged it. Please <a href="'+base_url+'">login</a></div>');
|
||||
}
|
||||
}
|
||||
// Put future Errorhandling here
|
||||
} else {
|
||||
if($('.radio_login_error').length != 0) {
|
||||
$(".radio_login_error" ).remove();
|
||||
}
|
||||
var band = frequencyToBand(data.frequency);
|
||||
|
||||
if (band !== $("#band").val()) {
|
||||
$("#band").val(band);
|
||||
$("#band").trigger("change");
|
||||
}
|
||||
|
||||
var minutes = Math.floor(cat_timeout_interval / 60);
|
||||
|
||||
if(data.updated_minutes_ago > minutes) {
|
||||
$(".radio_cat_state" ).remove();
|
||||
if($('.radio_timeout_error').length == 0) {
|
||||
$('.messages').prepend('<div class="alert alert-danger radio_timeout_error" role="alert"><i class="fas fa-broadcast-tower"></i> Radio connection timed-out: ' + $('select.radios option:selected').text() + ' data is ' + data.updated_minutes_ago + ' minutes old.</div>');
|
||||
} else {
|
||||
$('.radio_timeout_error').html('Radio connection timed-out: ' + $('select.radios option:selected').text() + ' data is ' + data.updated_minutes_ago + ' minutes old.');
|
||||
}
|
||||
} else {
|
||||
$(".radio_timeout_error" ).remove();
|
||||
text = '<i class="fas fa-broadcast-tower"></i><span style="margin-left:10px;"></span><b>TX:</b> '+(Math.round(parseInt(data.frequency)/100)/10000).toFixed(4)+' MHz';
|
||||
if(data.mode != null) {
|
||||
text = text+'<span style="margin-left:10px"></span>'+data.mode;
|
||||
}
|
||||
if(data.power != null && data.power != 0) {
|
||||
text = text+'<span style="margin-left:10px"></span>'+data.power+' W';
|
||||
}
|
||||
if (! $('#radio_cat_state').length) {
|
||||
$('.messages').prepend('<div aria-hidden="true"><div id="radio_cat_state" class="alert alert-success radio_cat_state" role="alert">'+text+'</div></div>');
|
||||
} else {
|
||||
$('#radio_cat_state').html(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Update frequency every three second
|
||||
setInterval(updateFromCAT, 3000);
|
||||
|
||||
// If a radios selected from drop down select radio update.
|
||||
$('.radios').change(updateFromCAT);
|
||||
177
assets/js/sections/bandmap_list.js
普通文件
177
assets/js/sections/bandmap_list.js
普通文件
|
|
@ -0,0 +1,177 @@
|
|||
$(function() {
|
||||
|
||||
function SortByQrg(a, b){
|
||||
var a = a.frequency;
|
||||
var b = b.frequency;
|
||||
return ((a< b) ? -1 : ((a> b) ? 1 : 0));
|
||||
}
|
||||
|
||||
|
||||
function fill_list(band,de,maxAgeMinutes) {
|
||||
var table = $('.spottable').DataTable();
|
||||
if ((band != '') && (band !== undefined)) {
|
||||
let dxurl = dxcluster_provider + "/spots/" + band + "/" +maxAgeMinutes + "/" + de;
|
||||
$.ajax({
|
||||
url: dxurl,
|
||||
cache: false,
|
||||
dataType: "json"
|
||||
}).done(function(dxspots) {
|
||||
table.page.len(50);
|
||||
let oldtable=table.data();
|
||||
table.clear();
|
||||
if (dxspots.length>0) {
|
||||
dxspots.sort(SortByQrg);
|
||||
dxspots.forEach((single) => {
|
||||
var data=[];
|
||||
data[0]=[];
|
||||
data[0].push(single.when_pretty);
|
||||
data[0].push(single.frequency + " kHz");
|
||||
data[0].push((single.worked_call ?'<span class="text-success">' : '')+single.spotted+(single.worked_call ? '</span>' : ''));
|
||||
data[0].push(single.dxcc_spotted.entity);
|
||||
data[0].push(single.spotter);
|
||||
if (oldtable.length > 0) {
|
||||
let update=false;
|
||||
oldtable.each( function (srow) {
|
||||
if (JSON.stringify(srow) === JSON.stringify(data[0])) {
|
||||
update=true;
|
||||
}
|
||||
});
|
||||
if (!update) { // Sth. Fresh? So highlight
|
||||
table.rows.add(data).draw().nodes().to$().addClass("fresh bg-info");
|
||||
} else {
|
||||
table.rows.add(data).draw();
|
||||
}
|
||||
} else {
|
||||
table.rows.add(data).draw();
|
||||
}
|
||||
});
|
||||
setTimeout(function(){ // Remove Highlights within 15sec
|
||||
$(".fresh").removeClass("bg-info");
|
||||
},1000);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
table.clear();
|
||||
table.draw();
|
||||
}
|
||||
}
|
||||
|
||||
function highlight_current_qrg(qrg) {
|
||||
var table=$('.spottable').DataTable();
|
||||
table.rows().every(function() {
|
||||
var d=this.data();
|
||||
var distance=Math.abs(parseInt(d[1].substring(0,d[1].length-4))-qrg);
|
||||
if (distance<=20) {
|
||||
distance++;
|
||||
alpha=(.5/distance);
|
||||
this.nodes().to$().css('background-color', 'rgba(0,0,255,' + alpha + ')');
|
||||
} else {
|
||||
this.nodes().to$().css('background-color', '');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$('.spottable').DataTable().order([1, 'asc']);
|
||||
$('.spottable').DataTable().clear();
|
||||
fill_list($('#band option:selected').val(), $('#decontSelect option:selected').val(),dxcluster_maxage);
|
||||
setInterval(function () { fill_list($('#band option:selected').val(), $('#decontSelect option:selected').val(),dxcluster_maxage); },60000);
|
||||
|
||||
$("#decontSelect").on("change",function() {
|
||||
$('.spottable').DataTable().clear();
|
||||
fill_list($('#band option:selected').val(), $('#decontSelect option:selected').val(),dxcluster_maxage);
|
||||
});
|
||||
|
||||
$("#band").on("change",function() {
|
||||
$('.spottable').DataTable().order([1, 'asc']);
|
||||
$('.spottable').DataTable().clear();
|
||||
fill_list($('#band option:selected').val(), $('#decontSelect option:selected').val(),dxcluster_maxage);
|
||||
});
|
||||
|
||||
$("#spottertoggle").on("click", function() {
|
||||
if ($('.spottable').DataTable().column(4).visible()) {
|
||||
$('.spottable').DataTable().column(4).visible(false);
|
||||
} else {
|
||||
$('.spottable').DataTable().column(4).visible(true);
|
||||
}
|
||||
});
|
||||
|
||||
$("#menutoggle").on("click", function() {
|
||||
if ($('.navbar').is(":hidden")) {
|
||||
$('.navbar').show();
|
||||
$('#dxtabs').show();
|
||||
$('#dxtitle').show();
|
||||
$('#menutoggle_i').removeClass('fa-arrow-down');
|
||||
$('#menutoggle_i').addClass('fa-arrow-up');
|
||||
} else {
|
||||
$('.navbar').hide();
|
||||
$('#dxtabs').hide();
|
||||
$('#dxtitle').hide();
|
||||
$('#menutoggle_i').removeClass('fa-arrow-up');
|
||||
$('#menutoggle_i').addClass('fa-arrow-down');
|
||||
}
|
||||
});
|
||||
|
||||
var updateFromCAT = function() {
|
||||
if($('select.radios option:selected').val() != '0') {
|
||||
radioID = $('select.radios option:selected').val();
|
||||
$.getJSON( base_url+"radio/json/" + radioID, function( data ) {
|
||||
|
||||
if (data.error) {
|
||||
if (data.error == 'not_logged_in') {
|
||||
$(".radio_cat_state" ).remove();
|
||||
if($('.radio_login_error').length == 0) {
|
||||
$('.messages').prepend('<div class="alert alert-danger radio_login_error" role="alert"><i class="fas fa-broadcast-tower"></i> You\'re not logged it. Please <a href="'+base_url+'">login</a></div>');
|
||||
}
|
||||
}
|
||||
// Put future Errorhandling here
|
||||
} else {
|
||||
if($('.radio_login_error').length != 0) {
|
||||
$(".radio_login_error" ).remove();
|
||||
}
|
||||
var band = frequencyToBand(data.frequency);
|
||||
|
||||
if (band !== $("#band").val()) {
|
||||
$("#band").val(band);
|
||||
$("#band").trigger("change");
|
||||
}
|
||||
|
||||
var minutes = Math.floor(cat_timeout_interval / 60);
|
||||
|
||||
if(data.updated_minutes_ago > minutes) {
|
||||
$(".radio_cat_state" ).remove();
|
||||
if($('.radio_timeout_error').length == 0) {
|
||||
$('.messages').prepend('<div class="alert alert-danger radio_timeout_error" role="alert"><i class="fas fa-broadcast-tower"></i> Radio connection timed-out: ' + $('select.radios option:selected').text() + ' data is ' + data.updated_minutes_ago + ' minutes old.</div>');
|
||||
} else {
|
||||
$('.radio_timeout_error').html('Radio connection timed-out: ' + $('select.radios option:selected').text() + ' data is ' + data.updated_minutes_ago + ' minutes old.');
|
||||
}
|
||||
} else {
|
||||
$(".radio_timeout_error" ).remove();
|
||||
text = '<i class="fas fa-broadcast-tower"></i><span style="margin-left:10px;"></span><b>TX:</b> '+(Math.round(parseInt(data.frequency)/100)/10000).toFixed(4)+' MHz';
|
||||
highlight_current_qrg((parseInt(data.frequency))/1000);
|
||||
if(data.mode != null) {
|
||||
text = text+'<span style="margin-left:10px"></span>'+data.mode;
|
||||
}
|
||||
if(data.power != null && data.power != 0) {
|
||||
text = text+'<span style="margin-left:10px"></span>'+data.power+' W';
|
||||
}
|
||||
if (! $('#radio_cat_state').length) {
|
||||
$('.messages').prepend('<div aria-hidden="true"><div id="radio_cat_state" class="alert alert-success radio_cat_state" role="alert">'+text+'</div></div>');
|
||||
} else {
|
||||
$('#radio_cat_state').html(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.dataTable.moment(custom_date_format + ' HH:mm');
|
||||
// Update frequency every three second
|
||||
setInterval(updateFromCAT, 3000);
|
||||
|
||||
// If a radios selected from drop down select radio update.
|
||||
$('.radios').change(updateFromCAT);
|
||||
|
||||
});
|
||||
|
||||
|
||||
270
src/Dxcc/Dxcc.php
普通文件
270
src/Dxcc/Dxcc.php
普通文件
|
|
@ -0,0 +1,270 @@
|
|||
<?php
|
||||
|
||||
namespace Cloudlog\Dxcc;
|
||||
|
||||
class Dxcc {
|
||||
protected $dxcc = array();
|
||||
protected $dxccexceptions = array();
|
||||
|
||||
function __construct($date)
|
||||
{
|
||||
$this->read_data($date);
|
||||
}
|
||||
|
||||
public function dxcc_lookup($call, $date) {
|
||||
|
||||
$csadditions = '/^P$|^R$|^A$|^M$/';
|
||||
$CI =& get_instance();
|
||||
|
||||
if (array_key_exists($call, $this->dxccexceptions)) {
|
||||
return $this->dxccexceptions[$call];
|
||||
} else {
|
||||
|
||||
if (preg_match('/(^KG4)[A-Z09]{3}/', $call)) { // KG4/ and KG4 5 char calls are Guantanamo Bay. If 4 or 6 char, it is USA
|
||||
$call = "K";
|
||||
} elseif (preg_match('/(^OH\/)|(\/OH[1-9]?$)/', $call)) { # non-Aland prefix!
|
||||
$call = "OH"; # make callsign OH = finland
|
||||
} elseif (preg_match('/(^CX\/)|(\/CX[1-9]?$)/', $call)) { # non-Antarctica prefix!
|
||||
$call = "CX"; # make callsign CX = Uruguay
|
||||
} elseif (preg_match('/(^3D2R)|(^3D2.+\/R)/', $call)) { # seems to be from Rotuma
|
||||
$call = "3D2/R"; # will match with Rotuma
|
||||
} elseif (preg_match('/^3D2C/', $call)) { # seems to be from Conway Reef
|
||||
$call = "3D2/C"; # will match with Conway
|
||||
} elseif (preg_match('/(^LZ\/)|(\/LZ[1-9]?$)/', $call)) { # LZ/ is LZ0 by DXCC but this is VP8h
|
||||
$call = "LZ";
|
||||
} elseif (preg_match('/(^KG4)[A-Z09]{2}/', $call)) {
|
||||
$call = "KG4";
|
||||
} elseif (preg_match('/(^KG4)[A-Z09]{1}/', $call)) {
|
||||
$call = "K";
|
||||
} elseif (preg_match('/\w\/\w/', $call)) {
|
||||
if (preg_match_all('/^((\d|[A-Z])+\/)?((\d|[A-Z]){3,})(\/(\d|[A-Z])+)?(\/(\d|[A-Z])+)?$/', $call, $matches)) {
|
||||
$prefix = $matches[1][0];
|
||||
$callsign = $matches[3][0];
|
||||
$suffix = $matches[5][0];
|
||||
if ($prefix) {
|
||||
$prefix = substr($prefix, 0, -1); # Remove the / at the end
|
||||
}
|
||||
if ($suffix) {
|
||||
$suffix = substr($suffix, 1); # Remove the / at the beginning
|
||||
};
|
||||
if (preg_match($csadditions, $suffix)) {
|
||||
if ($prefix) {
|
||||
$call = $prefix;
|
||||
} else {
|
||||
$call = $callsign;
|
||||
}
|
||||
} else {
|
||||
$result = $this->wpx($call, 1); # use the wpx prefix instead
|
||||
if ($result == '') {
|
||||
$row['adif'] = 0;
|
||||
$row['entity'] = '- NONE -';
|
||||
$row['cqz'] = 0;
|
||||
$row['long'] = '0';
|
||||
$row['lat'] = '0';
|
||||
return $row;
|
||||
} else {
|
||||
$call = $result . "AA";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$len = strlen($call);
|
||||
|
||||
// query the table, removing a character from the right until a match
|
||||
for ($i = $len; $i > 0; $i--){
|
||||
$result = '';
|
||||
|
||||
if (array_key_exists(substr($call, 0, $i), $this->dxcc)) {
|
||||
return $this->dxcc[substr($call, 0, $i)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array("Not Found", "Not Found");
|
||||
}
|
||||
|
||||
function wpx($testcall, $i) {
|
||||
$prefix = '';
|
||||
$a = '';
|
||||
$b = '';
|
||||
$c = '';
|
||||
|
||||
$lidadditions = '/^QRP$|^LGT$/';
|
||||
$csadditions = '/^P$|^R$|^A$|^M$|^LH$/';
|
||||
$noneadditions = '/^MM$|^AM$/';
|
||||
|
||||
# First check if the call is in the proper format, A/B/C where A and C
|
||||
# are optional (prefix of guest country and P, MM, AM etc) and B is the
|
||||
# callsign. Only letters, figures and "/" is accepted, no further check if the
|
||||
# callsign "makes sense".
|
||||
# 23.Apr.06: Added another "/X" to the regex, for calls like RV0AL/0/P
|
||||
# as used by RDA-DXpeditions....
|
||||
|
||||
if (preg_match_all('/^((\d|[A-Z])+\/)?((\d|[A-Z]){3,})(\/(\d|[A-Z])+)?(\/(\d|[A-Z])+)?$/', $testcall, $matches)) {
|
||||
|
||||
# Now $1 holds A (incl /), $3 holds the callsign B and $5 has C
|
||||
# We save them to $a, $b and $c respectively to ensure they won't get
|
||||
# lost in further Regex evaluations.
|
||||
$a = $matches[1][0];
|
||||
$b = $matches[3][0];
|
||||
$c = $matches[5][0];
|
||||
|
||||
if ($a) {
|
||||
$a = substr($a, 0, -1); # Remove the / at the end
|
||||
}
|
||||
if ($c) {
|
||||
$c = substr($c, 1); # Remove the / at the beginning
|
||||
};
|
||||
|
||||
# In some cases when there is no part A but B and C, and C is longer than 2
|
||||
# letters, it happens that $a and $b get the values that $b and $c should
|
||||
# have. This often happens with liddish callsign-additions like /QRP and
|
||||
# /LGT, but also with calls like DJ1YFK/KP5. ~/.yfklog has a line called
|
||||
# "lidadditions", which has QRP and LGT as defaults. This sorts out half of
|
||||
# the problem, but not calls like DJ1YFK/KH5. This is tested in a second
|
||||
# try: $a looks like a call (.\d[A-Z]) and $b doesn't (.\d), they are
|
||||
# swapped. This still does not properly handle calls like DJ1YFK/KH7K where
|
||||
# only the OP's experience says that it's DJ1YFK on KH7K.
|
||||
if (!$c && $a && $b) { # $a and $b exist, no $c
|
||||
if (preg_match($lidadditions, $b)) { # check if $b is a lid-addition
|
||||
$b = $a;
|
||||
$a = null; # $a goes to $b, delete lid-add
|
||||
} elseif ((preg_match('/\d[A-Z]+$/', $a)) && (preg_match('/\d$/', $b))) { # check for call in $a
|
||||
$temp = $b;
|
||||
$b = $a;
|
||||
$a = $temp;
|
||||
}
|
||||
}
|
||||
|
||||
# *** Added later *** The check didn't make sure that the callsign
|
||||
# contains a letter. there are letter-only callsigns like RAEM, but not
|
||||
# figure-only calls.
|
||||
|
||||
if (preg_match('/^[0-9]+$/', $b)) { # Callsign only consists of numbers. Bad!
|
||||
return null; # exit, undef
|
||||
}
|
||||
|
||||
# Depending on these values we have to determine the prefix.
|
||||
# Following cases are possible:
|
||||
#
|
||||
# 1. $a and $c undef --> only callsign, subcases
|
||||
# 1.1 $b contains a number -> everything from start to number
|
||||
# 1.2 $b contains no number -> first two letters plus 0
|
||||
# 2. $a undef, subcases:
|
||||
# 2.1 $c is only a number -> $a with changed number
|
||||
# 2.2 $c is /P,/M,/MM,/AM -> 1.
|
||||
# 2.3 $c is something else and will be interpreted as a Prefix
|
||||
# 3. $a is defined, will be taken as PFX, regardless of $c
|
||||
|
||||
if (($a == null) && ($c == null)) { # Case 1
|
||||
if (preg_match('/\d/', $b)) { # Case 1.1, contains number
|
||||
preg_match('/(.+\d)[A-Z]*/', $b, $matches); # Prefix is all but the last
|
||||
$prefix = $matches[1]; # Letters
|
||||
} else { # Case 1.2, no number
|
||||
$prefix = substr($b, 0, 2) . "0"; # first two + 0
|
||||
}
|
||||
} elseif (($a == null) && (isset($c))) { # Case 2, CALL/X
|
||||
if (preg_match('/^(\d)/', $c)) { # Case 2.1, number
|
||||
preg_match('/(.+\d)[A-Z]*/', $b, $matches); # regular Prefix in $1
|
||||
# Here we need to find out how many digits there are in the
|
||||
# prefix, because for example A45XR/0 is A40. If there are 2
|
||||
# numbers, the first is not deleted. If course in exotic cases
|
||||
# like N66A/7 -> N7 this brings the wrong result of N67, but I
|
||||
# think that's rather irrelevant cos such calls rarely appear
|
||||
# and if they do, it's very unlikely for them to have a number
|
||||
# attached. You can still edit it by hand anyway..
|
||||
if (preg_match('/^([A-Z]\d)\d$/', $matches[1])) { # e.g. A45 $c = 0
|
||||
$prefix = $matches[1] . $c; # -> A40
|
||||
} else { # Otherwise cut all numbers
|
||||
preg_match('/(.*[A-Z])\d+/', $matches[1], $match); # Prefix w/o number in $1
|
||||
$prefix = $match[1] . $c; # Add attached number
|
||||
}
|
||||
} elseif (preg_match($csadditions, $c)) {
|
||||
preg_match('/(.+\d)[A-Z]*/', $b, $matches); # Known attachment -> like Case 1.1
|
||||
$prefix = $matches[1];
|
||||
} elseif (preg_match($noneadditions, $c)) {
|
||||
return '';
|
||||
} elseif (preg_match('/^\d\d+$/', $c)) { # more than 2 numbers -> ignore
|
||||
preg_match('/(.+\d)[A-Z]* /', $b, $matches); # see above
|
||||
$prefix = $matches[1][0];
|
||||
} else { # Must be a Prefix!
|
||||
if (preg_match('/\d$/', $c)) { # ends in number -> good prefix
|
||||
$prefix = $c;
|
||||
} else { # Add Zero at the end
|
||||
$prefix = $c . "0";
|
||||
}
|
||||
}
|
||||
} elseif (($a) && (preg_match($noneadditions, $c))) { # Case 2.1, X/CALL/X ie TF/DL2NWK/MM - DXCC none
|
||||
return '';
|
||||
} elseif ($a) {
|
||||
# $a contains the prefix we want
|
||||
if (preg_match('/\d$/', $a)) { # ends in number -> good prefix
|
||||
$prefix = $a;
|
||||
} else { # add zero if no number
|
||||
$prefix = $a . "0";
|
||||
}
|
||||
}
|
||||
# In very rare cases (right now I can only think of KH5K and KH7K and FRxG/T
|
||||
# etc), the prefix is wrong, for example KH5K/DJ1YFK would be KH5K0. In this
|
||||
# case, the superfluous part will be cropped. Since this, however, changes the
|
||||
# DXCC of the prefix, this will NOT happen when invoked from with an
|
||||
# extra parameter $_[1]; this will happen when invoking it from &dxcc.
|
||||
|
||||
if (preg_match('/(\w+\d)[A-Z]+\d/', $prefix, $matches) && $i == null) {
|
||||
$prefix = $matches[1][0];
|
||||
}
|
||||
return $prefix;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read cty.dat from AD1C
|
||||
*/
|
||||
function read_data($date) {
|
||||
$CI =& get_instance();
|
||||
$dxcc_exceptions = $CI->db->select('`entity`, `adif`, `cqz`, `start`, `end`, `call`, `cont`, `long`, `lat`')
|
||||
->where('(start <= ', $date)
|
||||
->or_where('start is null)', NULL, false)
|
||||
->where('(end >= ', $date)
|
||||
->or_where('end is null)', NULL, false)
|
||||
->get('dxcc_exceptions');
|
||||
|
||||
if ($dxcc_exceptions->num_rows() > 0){
|
||||
foreach ($dxcc_exceptions->result() as $dxcce) {
|
||||
$this->dxccexceptions[$dxcce->call]['adif'] = $dxcce->adif;
|
||||
$this->dxccexceptions[$dxcce->call]['cont'] = $dxcce->cont;
|
||||
$this->dxccexceptions[$dxcce->call]['entity'] = $dxcce->entity;
|
||||
$this->dxccexceptions[$dxcce->call]['cqz'] = $dxcce->cqz;
|
||||
$this->dxccexceptions[$dxcce->call]['start'] = $dxcce->start;
|
||||
$this->dxccexceptions[$dxcce->call]['end'] = $dxcce->end;
|
||||
$this->dxccexceptions[$dxcce->call]['long'] = $dxcce->long;
|
||||
$this->dxccexceptions[$dxcce->call]['lat'] = $dxcce->lat;
|
||||
}
|
||||
}
|
||||
|
||||
$dxcc_result = $CI->db->select('*')
|
||||
->where('(start <= ', $date)
|
||||
->or_where("start is null)", NULL, false)
|
||||
->where('(end >= ', $date)
|
||||
->or_where("end is null)", NULL, false)
|
||||
->get('dxcc_prefixes');
|
||||
|
||||
if ($dxcc_result->num_rows() > 0){
|
||||
foreach ($dxcc_result->result() as $dx) {
|
||||
$this->dxcc[$dx->call]['adif'] = $dx->adif;
|
||||
$this->dxcc[$dx->call]['cont'] = $dx->cont;
|
||||
$this->dxcc[$dx->call]['entity'] = $dx->entity;
|
||||
$this->dxcc[$dx->call]['cqz'] = $dx->cqz;
|
||||
$this->dxcc[$dx->call]['start'] = $dx->start;
|
||||
$this->dxcc[$dx->call]['end'] = $dx->end;
|
||||
$this->dxcc[$dx->call]['long'] = $dx->long;
|
||||
$this->dxcc[$dx->call]['lat'] = $dx->lat;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
正在加载…
在新工单中引用