New feature: timeplotter
这个提交包含在:
父节点
93730f37e7
当前提交
66365a7e55
共有 5 个文件被更改,包括 353 次插入 和 1 次删除
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||||
|
|
||||||
|
class Timeplotter 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'); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
// Render Page
|
||||||
|
$data['page_title'] = "Timeplotter";
|
||||||
|
|
||||||
|
$this->load->model('Timeplotter_model');
|
||||||
|
|
||||||
|
$data['worked_bands'] = $this->Timeplotter_model->get_worked_bands();
|
||||||
|
|
||||||
|
$this->load->model('dxcc');
|
||||||
|
$data['dxcc_list'] = $this->dxcc->list();
|
||||||
|
|
||||||
|
$this->load->model('modes');
|
||||||
|
|
||||||
|
$data['modes'] = $this->modes->active();
|
||||||
|
|
||||||
|
$this->load->view('interface_assets/header', $data);
|
||||||
|
$this->load->view('timeplotter/index');
|
||||||
|
$this->load->view('interface_assets/footer');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTimes() {
|
||||||
|
// POST data
|
||||||
|
$postData = $this->input->post();
|
||||||
|
|
||||||
|
//load model
|
||||||
|
$this->load->model('Timeplotter_model');
|
||||||
|
|
||||||
|
// get data
|
||||||
|
$data = $this->Timeplotter_model->getTimes($postData);
|
||||||
|
|
||||||
|
return json_encode($data);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,151 @@
|
||||||
|
<?php
|
||||||
|
if (!defined('BASEPATH')) exit('No direct script access allowed');
|
||||||
|
|
||||||
|
class Timeplotter_model extends CI_Model
|
||||||
|
{
|
||||||
|
function __construct()
|
||||||
|
{
|
||||||
|
// Call the Model constructor
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_worked_bands() {
|
||||||
|
$CI =& get_instance();
|
||||||
|
$CI->load->model('Stations');
|
||||||
|
$station_id = $CI->Stations->find_active();
|
||||||
|
|
||||||
|
$data = $this->db->query(
|
||||||
|
"SELECT distinct LOWER(`COL_BAND`) as `COL_BAND` FROM `" . $this->config->item('table_name') . "` WHERE station_id = " . $station_id . " AND COL_PROP_MODE != \"SAT\""
|
||||||
|
);
|
||||||
|
$worked_slots = array();
|
||||||
|
foreach ($data->result() as $row) {
|
||||||
|
array_push($worked_slots, $row->COL_BAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
$SAT_data = $this->db->query(
|
||||||
|
"SELECT distinct LOWER(`COL_PROP_MODE`) as `COL_PROP_MODE` FROM `" . $this->config->item('table_name') . "` WHERE station_id = " . $station_id . " AND COL_PROP_MODE = \"SAT\""
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($SAT_data->result() as $row) {
|
||||||
|
array_push($worked_slots, strtoupper($row->COL_PROP_MODE));
|
||||||
|
}
|
||||||
|
|
||||||
|
// bring worked-slots in order of defined $bandslots
|
||||||
|
$results = array();
|
||||||
|
foreach (array_keys($this->bandslots) as $slot) {
|
||||||
|
if (in_array($slot, $worked_slots)) {
|
||||||
|
array_push($results, $slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public $bandslots = array("160m" => 0,
|
||||||
|
"80m" => 0,
|
||||||
|
"60m" => 0,
|
||||||
|
"40m" => 0,
|
||||||
|
"30m" => 0,
|
||||||
|
"20m" => 0,
|
||||||
|
"17m" => 0,
|
||||||
|
"15m" => 0,
|
||||||
|
"12m" => 0,
|
||||||
|
"10m" => 0,
|
||||||
|
"6m" => 0,
|
||||||
|
"4m" => 0,
|
||||||
|
"2m" => 0,
|
||||||
|
"70cm" => 0,
|
||||||
|
"23cm" => 0,
|
||||||
|
"13cm" => 0,
|
||||||
|
"9cm" => 0,
|
||||||
|
"6cm" => 0,
|
||||||
|
"3cm" => 0,
|
||||||
|
"1.25cm" => 0,
|
||||||
|
"SAT" => 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
function getTimes($postdata) {
|
||||||
|
$CI =& get_instance();
|
||||||
|
$CI->load->model('Stations');
|
||||||
|
$station_id = $CI->Stations->find_active();
|
||||||
|
|
||||||
|
$this->db->select('time(col_time_on) time, col_call as callsign');
|
||||||
|
|
||||||
|
if ($postdata['band'] != 'All') {
|
||||||
|
if ($postdata['band'] == 'sat') {
|
||||||
|
$this->db->where('col_prop_mode', $postdata['band']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->db->where('col_band', $postdata['band']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($postdata['dxcc'] != 'All') {
|
||||||
|
$this->db->where('col_dxcc', $postdata['dxcc']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($postdata['cqzone'] != 'All') {
|
||||||
|
$this->db->where('col_cqz', $postdata['cqzone']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->db->where('station_id', $station_id);
|
||||||
|
$datearray = $this->db->get($this->config->item('table_name'));
|
||||||
|
$this->plot($datearray->result_array());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function generates the array, checks for array entries, and adds them before returning data ready for plot
|
||||||
|
*/
|
||||||
|
function plot($log) {
|
||||||
|
|
||||||
|
$start = "00:00";
|
||||||
|
$end = "23:59";
|
||||||
|
|
||||||
|
$tStart = strtotime($start);
|
||||||
|
$tEnd = strtotime($end);
|
||||||
|
$tNow = $tStart;
|
||||||
|
$i = 0;
|
||||||
|
|
||||||
|
while($tNow <= $tEnd){ // Generates the time array
|
||||||
|
$label = date("H:i",$tNow).'z - ';
|
||||||
|
$tNow = strtotime('+30 minutes',$tNow);
|
||||||
|
$label .= date("H:i",$tNow).'z';
|
||||||
|
$dataarray[$i]['time'] = $label; // Used in x-axis of graph to show label for the timeslot
|
||||||
|
$dataarray[$i]['count'] = '0'; // Used to hold number of contacts found in the timeslot
|
||||||
|
$dataarray[$i]['calls'] = ''; // Used for holding callsigns of contacts in that timeslot
|
||||||
|
$dataarray[$i]['callcount'] = '0'; // Used for counting how many callsigns stored in that timeslot
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($log as $line) { // Looping through all the timestamps found in the log
|
||||||
|
$time = $line['time']; // Resolution is 30, calculates where to put result in array
|
||||||
|
$dt = new DateTime("1970-01-01 $time", new DateTimeZone('UTC'));
|
||||||
|
$arrayplacement = (int)$dt->getTimestamp();
|
||||||
|
$arrayplacement = floor($arrayplacement / 1800);
|
||||||
|
$dataarray[$arrayplacement]['count']++;
|
||||||
|
|
||||||
|
$callCount = $dataarray[$arrayplacement]['callcount'];
|
||||||
|
|
||||||
|
if ($callCount < 5) { // We only save a max of 5 calls to show in the graph
|
||||||
|
if ($callCount > 0) {
|
||||||
|
$dataarray[$arrayplacement]['calls'] .= ', ';
|
||||||
|
}
|
||||||
|
$dataarray[$arrayplacement]['calls'] .= $line['callsign'];
|
||||||
|
$dataarray[$arrayplacement]['callcount']++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($log) != 0) { // If we have a result from the log
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
$data['qsocount'] = count($log);
|
||||||
|
$data['ok'] = 'OK';
|
||||||
|
$data['qsodata'] = $dataarray;
|
||||||
|
echo json_encode($data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
$data['error'] = 'No qsoes to plot found!';
|
||||||
|
echo json_encode($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2042,5 +2042,95 @@ $(document).ready(function(){
|
||||||
</script>
|
</script>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
||||||
|
<?php if ($this->uri->segment(1) == "timeplotter") { ?>
|
||||||
|
<script src="https://code.highcharts.com/stock/highstock.js"></script>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function timeplot(form) {
|
||||||
|
$(".ld-ext-right").addClass('running');
|
||||||
|
$(".ld-ext-right").prop('disabled', true);
|
||||||
|
$(".alert").remove();
|
||||||
|
var baseURL= "<?php echo base_url();?>";
|
||||||
|
$.ajax({
|
||||||
|
url: baseURL+'index.php/timeplotter/getTimes',
|
||||||
|
type: 'post',
|
||||||
|
data: {'band': form.band.value, 'dxcc': form.dxcc.value, 'cqzone': form.cqzone.value},
|
||||||
|
success: function(tmp) {
|
||||||
|
$(".ld-ext-right").removeClass('running');
|
||||||
|
$(".ld-ext-right").prop('disabled', false);
|
||||||
|
if (tmp.ok == 'OK') {
|
||||||
|
plotTimeplotterChart(tmp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$("#container").remove();
|
||||||
|
$("#info").remove();
|
||||||
|
$("#timeplotter_div").append('<div class="alert alert-danger"><a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>\n' +
|
||||||
|
tmp.error +
|
||||||
|
'</div>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function plotTimeplotterChart(tmp) {
|
||||||
|
$("#container").remove();
|
||||||
|
$("#info").remove();
|
||||||
|
$("#timeplotter_div").append('<p id="info">' + tmp.qsocount + ' contacts were plotted.</p><div id="container" style="height: 600px;"></div>');
|
||||||
|
var options = {
|
||||||
|
chart: {
|
||||||
|
type: 'column',
|
||||||
|
zoomType: 'xy',
|
||||||
|
renderTo: 'container'
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
text: 'Time distribution'
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
categories: [],
|
||||||
|
crosshair: true,
|
||||||
|
type: "category",
|
||||||
|
min:0,
|
||||||
|
max:47,
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
title: {
|
||||||
|
text: '# QSOes'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rangeSelector: {
|
||||||
|
selected: 1
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
formatter: function () {
|
||||||
|
if(this.point) {
|
||||||
|
return "Time: " + options.xAxis.categories[this.point.x] +
|
||||||
|
"<br />Callsign(s) worked (max 5): " + myComments[this.point.x] +
|
||||||
|
"<br />Number of qsos: <strong>" + series.data[this.point.x] + "</strong>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: []
|
||||||
|
};
|
||||||
|
var myComments=[];
|
||||||
|
|
||||||
|
var series = {
|
||||||
|
data: []
|
||||||
|
};
|
||||||
|
|
||||||
|
$.each(tmp.qsodata, function(){
|
||||||
|
myComments.push(this.calls);
|
||||||
|
options.xAxis.categories.push(this.time);
|
||||||
|
series.name = 'Number of qsos';
|
||||||
|
series.data.push(this.count);
|
||||||
|
});
|
||||||
|
|
||||||
|
options.series.push(series);
|
||||||
|
|
||||||
|
var chart = new Highcharts.Chart(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<?php } ?>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
<link rel="stylesheet" type="text/css" href="<?php echo base_url(); ?>assets/plugins/quill/quill.snow.css" />
|
<link rel="stylesheet" type="text/css" href="<?php echo base_url(); ?>assets/plugins/quill/quill.snow.css" />
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
||||||
<?php if ($this->uri->segment(1) == "qrz" || $this->uri->segment(1) == "accumulated") { ?>
|
<?php if ($this->uri->segment(1) == "qrz" || $this->uri->segment(1) == "accumulated" || $this->uri->segment(1) == "timeplotter") { ?>
|
||||||
<link rel="stylesheet" type="text/css" href="<?php echo base_url(); ?>assets/css/loading.min.css" />
|
<link rel="stylesheet" type="text/css" href="<?php echo base_url(); ?>assets/css/loading.min.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="<?php echo base_url(); ?>assets/css/ldbtn.min.css" />
|
<link rel="stylesheet" type="text/css" href="<?php echo base_url(); ?>assets/css/ldbtn.min.css" />
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
@ -86,6 +86,8 @@
|
||||||
<a class="dropdown-item" href="<?php echo site_url('timeline');?>" title="Dxcctimeline">DXCC Timeline</a>
|
<a class="dropdown-item" href="<?php echo site_url('timeline');?>" title="Dxcctimeline">DXCC Timeline</a>
|
||||||
<div class="dropdown-divider"></div>
|
<div class="dropdown-divider"></div>
|
||||||
<a class="dropdown-item" href="<?php echo site_url('accumulated');?>" title="Dxcctimeline">Accumulated statistics</a>
|
<a class="dropdown-item" href="<?php echo site_url('accumulated');?>" title="Dxcctimeline">Accumulated statistics</a>
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
<a class="dropdown-item" href="<?php echo site_url('timeplotter');?>" title="View time when worked">Timeplotter</a>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
<div class="container">
|
||||||
|
<h2><?php echo $page_title; ?></h1>
|
||||||
|
<p>This tool is used to analyze your log to find out when you have worked a certain cq zone or dxcc on a chosen band.</p>
|
||||||
|
<form class="form">
|
||||||
|
|
||||||
|
<div class="form-group row">
|
||||||
|
<label class="col-md-1 control-label" for="band">Band</label>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<select id="band" name="band" class="form-control custom-select">
|
||||||
|
<option value="All">All</option>
|
||||||
|
<?php foreach($worked_bands as $band) {
|
||||||
|
echo '<option value="' . $band . '">' . $band . '</option>'."\n";
|
||||||
|
} ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label class="col-md-1 control-label" for="dxcc">DXCC</label>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<select id="dxcc" name="dxcc" class="form-control custom-select">
|
||||||
|
<option value = 'All'>All</option>
|
||||||
|
<?php
|
||||||
|
if ($dxcc_list->num_rows() > 0) {
|
||||||
|
foreach ($dxcc_list->result() as $dxcc) {
|
||||||
|
echo '<option value=' . $dxcc->adif . '> ' . $dxcc->name . ' - ' . $dxcc->prefix;
|
||||||
|
if ($dxcc->end != null) {
|
||||||
|
echo ' (deleted)';
|
||||||
|
}
|
||||||
|
echo '</option>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group row">
|
||||||
|
<label class="col-md-1 control-label" for="cqzone">CQ Zone</label>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<select id="cqzone" name="cqzone" class="form-control custom-select">
|
||||||
|
<option value = 'All'>All</option>
|
||||||
|
<?php
|
||||||
|
for ($i = 1; $i<=40; $i++) {
|
||||||
|
echo '<option value='. $i . '>'. $i .'</option>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group row">
|
||||||
|
<div class="col-md-3">
|
||||||
|
<button id="button1id" type="button" name="button1id" class="btn btn-success btn-primary ld-ext-right" onclick="timeplot(this.form);">Show<div class="ld ld-ring ld-spin"></div></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div id="timeplotter_div">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
正在加载…
在新工单中引用