diff --git a/application/controllers/Dayswithqso.php b/application/controllers/Dayswithqso.php
index f280632f4..534464749 100644
--- a/application/controllers/Dayswithqso.php
+++ b/application/controllers/Dayswithqso.php
@@ -3,59 +3,114 @@ defined('BASEPATH') OR exit('No direct script access allowed');
class Dayswithqso extends CI_Controller {
- function __construct()
- {
- parent::__construct();
+ function __construct()
+ {
+ parent::__construct();
- $this->load->model('user_model');
- if(!$this->user_model->authorize(2)) { $this->session->set_flashdata('error', __("You're not allowed to do that!")); redirect('dashboard'); }
- }
+ $this->load->model('user_model');
+ if(!$this->user_model->authorize(2)) { $this->session->set_flashdata('error', __("You're not allowed to do that!")); redirect('dashboard'); }
+ }
- public function index() {
+ public function index() {
$this->load->model('dayswithqso_model');
- // Render Page
- $data['page_title'] = __("Days with QSOs");
+ // Render Page
+ $data['page_title'] = __("Days with QSOs");
- $data['result'] = $this->dayswithqso_model->getDaysWithQso();
- $data['streaks'] = $this->dayswithqso_model->getLongestStreak();
- $data['currentstreak'] = $this->dayswithqso_model->getCurrentStreak();
- $data['almostcurrentstreak'] = $this->dayswithqso_model->getAlmostCurrentStreak();
+ $data['result'] = $this->dayswithqso_model->getDaysWithQso();
+ $data['streaks'] = $this->dayswithqso_model->getLongestStreak();
+ $data['currentstreak'] = $this->dayswithqso_model->getCurrentStreak();
+ $data['almostcurrentstreak'] = $this->dayswithqso_model->getAlmostCurrentStreak();
$data['daysofweek'] = $this->dayswithqso_model->getDaysOfWeek();
+ $data['years'] = $this->get_years();
- $this->load->view('interface_assets/header', $data);
- $this->load->view('dayswithqso/index');
- $this->load->view('interface_assets/footer');
- }
+ $footerData = [];
+ $footerData['scripts'] = ['assets/js/jquery.glanceyear.js'];
- public function get_days(){
+ $this->load->view('interface_assets/header', $data);
+ $this->load->view('dayswithqso/index');
+ $this->load->view('interface_assets/footer',$footerData);
+ }
- //load model
- $this->load->model('dayswithqso_model');
+ function get_years() {
+ $this->load->model('logbook_model');
+ $totals_year = $this->logbook_model->totals_year();
+ $years=[];
+ if ($totals_year) {
+ foreach($totals_year->result() as $years_obj) {
+ $years[] = $years_obj->year;
+ }
+ }
+ return $years;
+ }
- // get data
- $data = $this->dayswithqso_model->getDaysWithQso();
- header('Content-Type: application/json');
- echo json_encode($data);
- }
+ public function get_punchvals($yr = null) {
+ $punchvals=[];
+ if (($yr ?? '') != '') {
+ $this->load->model('dayswithqso_model');
+ $res_punchvals = $this->dayswithqso_model->getPunchvals($this->security->xss_clean($yr));
+ if ($res_punchvals) {
+ foreach($res_punchvals as $pobj) {
+ $col=0;
+ switch (true) {
+ case ($pobj->qsos == 0):
+ $col=0;
+ break;
+ case ($pobj->qsos <= 3):
+ $col=3;
+ break;
+ case ($pobj->qsos <= 6):
+ $col=6;
+ break;
+ case ($pobj->qsos <= 12):
+ $col=12;
+ break;
+ case ($pobj->qsos <= 24):
+ $col=24;
+ break;
+ case ($pobj->qsos > 24):
+ $col=48;
+ break;
+ }
+ $punchvals[] = ['date' => $pobj->date, 'value' => $pobj->qsos, 'col' => $col];
+ }
+ }
+ } else {
+ $punchvals=[];
+ }
+ header('Content-Type: application/json');
+ echo json_encode($punchvals);
+ }
+
+
+ public function get_days(){
+
+ //load model
+ $this->load->model('dayswithqso_model');
+
+ // get data
+ $data = $this->dayswithqso_model->getDaysWithQso();
+ header('Content-Type: application/json');
+ echo json_encode($data);
+ }
public function get_weekdays() {
- //load model
- $this->load->model('dayswithqso_model');
+ //load model
+ $this->load->model('dayswithqso_model');
- // get data
- $data = $this->dayswithqso_model->getDaysOfWeek();
- header('Content-Type: application/json');
- echo json_encode($data);
- }
+ // get data
+ $data = $this->dayswithqso_model->getDaysOfWeek();
+ header('Content-Type: application/json');
+ echo json_encode($data);
+ }
public function get_months() {
- //load model
- $this->load->model('dayswithqso_model');
+ //load model
+ $this->load->model('dayswithqso_model');
- // get data
- $data = $this->dayswithqso_model->getMonthsOfYear();
- header('Content-Type: application/json');
- echo json_encode($data);
- }
+ // get data
+ $data = $this->dayswithqso_model->getMonthsOfYear();
+ header('Content-Type: application/json');
+ echo json_encode($data);
+ }
}
diff --git a/application/models/Dayswithqso_model.php b/application/models/Dayswithqso_model.php
index 518c1ef3c..1b1a0423d 100644
--- a/application/models/Dayswithqso_model.php
+++ b/application/models/Dayswithqso_model.php
@@ -178,6 +178,28 @@ class Dayswithqso_model extends CI_Model
return $query->result();
}
+ function getPunchvals($yr) {
+ $this->load->model('logbooks_model');
+ $logbooks_locations_array = $this->logbooks_model->list_logbook_relationships($this->session->userdata('active_station_logbook'));
+
+ if (!$logbooks_locations_array) {
+ return null;
+ }
+
+ $location_list = "'".implode("','",$logbooks_locations_array)."'";
+ $bindings=[];
+
+ $sql = "select count(1) as qsos, date_format(col_time_on,'%Y-%c-%e') as date from "
+ .$this->config->item('table_name'). " thcv
+ where station_id in (" . $location_list . ") and col_time_on >= ? and col_time_on <= ? group by date_format(col_time_on,'%Y-%c-%e')";
+ $bindings[]=$yr.'-01-01 00:00:00';
+ $bindings[]=$yr.'-12-31 23:59:59';
+
+ $query = $this->db->query($sql,$bindings);
+
+ return $query->result();
+ }
+
/*
* Returns the total number of QSOs made for each day of the week (Monday to Sunday)
*/
diff --git a/application/views/dayswithqso/index.php b/application/views/dayswithqso/index.php
index e10cfc69f..aefe13bc4 100644
--- a/application/views/dayswithqso/index.php
+++ b/application/views/dayswithqso/index.php
@@ -22,6 +22,9 @@
= __("Streaks"); ?>
+
+ = __("QSOs of Year"); ?>
+
@@ -64,12 +67,45 @@
-
+
= __('QSOs breakdown by month of the year'); ?>
+
+
+
+
+
+
+
+
+
+
+
+ Less
+
+
+
+
+ More
+
+ Calendar with QSOs
+
+
+
+
+
+
= __("Longest streak with QSOs in the log"); ?>
@@ -161,5 +197,6 @@
}
?>
+
diff --git a/assets/js/jquery.glanceyear.js b/assets/js/jquery.glanceyear.js
new file mode 100644
index 000000000..0403ad7ba
--- /dev/null
+++ b/assets/js/jquery.glanceyear.js
@@ -0,0 +1,168 @@
+(function($) {
+ $.fn.glanceyear = function(massive, options) {
+
+ var $_this = $(this);
+
+ var settings = $.extend({
+ eventClick: function(e) { alert('Date: ' + e.date + ', Count:' + e.count); },
+ months: ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],
+ weeks: ['M','T','W','T','F','S', 'S'],
+ targetQuantity: '.glanceyear-quantity',
+ tagId: 'glanceyear-svgTag',
+ showToday: false,
+ today: new Date()
+ }, options );
+
+ var svgElement = createElementSvg('svg', {'width': 54*12+15, 'height': 7*12+15 } );
+
+ var gElementContainer = createElementSvg('g', {'transform': 'translate(15, 15)'} );
+
+ var $_tag = $('')
+ .addClass('svg-tag')
+ .attr('id', settings.tagId)
+ .appendTo( $('body') )
+ .hide();
+
+ var dayCount = 366;
+ var monthCount;
+
+
+ //Weeks
+ for (var i=0; i<54; i++) {
+ var gElement = createElementSvg('g', {'transform': 'translate('+(12*i)+',0)'} );
+ var firstDate = new Date();
+ firstDate.setMonth(settings.today.getMonth());
+ firstDate.setFullYear(settings.today.getFullYear());
+ firstDate.setDate(settings.today.getDate() - dayCount-1);
+
+ var daysLeft = daysInMonth(firstDate) - firstDate.getDate();
+
+ // Days in week
+ for (var j=firstDate.getDay(); j<7 ; j++) {
+
+ var rectDate = new Date();
+ rectDate.setMonth(settings.today.getMonth());
+ rectDate.setFullYear(settings.today.getFullYear());
+ rectDate.setDate(settings.today.getDate() - dayCount);
+
+ if ( rectDate.getMonth() != monthCount && i < 52 && j > 3 && daysLeft > 7) {
+ //new Month
+ var textMonth = createElementSvg('text', {'x': 12*i, 'y':'-6', 'class':'month'} );
+ textMonth.textContent = getNameMonth(rectDate.getMonth());
+ gElementContainer.appendChild(textMonth);
+ monthCount = rectDate.getMonth();
+ }
+
+ dayCount--;
+ if (dayCount>=0 || (settings.showToday && dayCount>=-1)) {
+ // Day-obj factory
+
+ var rectElement = createElementSvg('rect', {
+ 'class': 'day',
+ 'width': '10px',
+ 'height': '10px',
+ 'data-date': rectDate.getFullYear()+'-'+(rectDate.getMonth()+1)+'-'+rectDate.getDate(),
+ 'y': 12*j
+ });
+
+ rectElement.onmouseover = function() {
+ var dateString = $(this).attr('data-date').split('-');
+ var date = new Date(dateString[0], dateString[1]-1, dateString[2]);
+
+ var tagDate = getBeautyDate(date);
+ var tagCount = $(this).attr('data-count');
+ var tagCountData = $(this).attr('data-count');
+
+ if (tagCountData) {
+ if (tagCountData > 1 )
+ tagCount = $(this).attr('data-count')+' scores';
+ else
+ tagCount = $(this).attr('data-count')+' score';
+ } else {
+ tagCount = 'No scores';
+ }
+
+ $_tag.html( '' + tagCount + ' on ' + tagDate)
+ .show()
+ .css({
+ 'left': $(this).offset().left - $_tag.outerWidth()/2+5,
+ 'top': $(this).offset().top-33
+ });
+ };
+
+ rectElement.onmouseleave = function() {
+ $_tag.text('').hide();
+ }
+
+ rectElement.onclick = function() {
+ settings.eventClick(
+ {
+ date: $(this).attr('data-date'),
+ count: $(this).attr('data-count') || 0
+ }
+ );
+
+ }
+
+ gElement.appendChild(rectElement);
+ }
+ }
+
+ gElementContainer.appendChild(gElement);
+ }
+ var textM = createElementSvg('text', {'x':'-14', 'y':'8'} );
+ textM.textContent = getNameWeek(0);
+ gElementContainer.appendChild(textM);
+ var textW = createElementSvg('text', {'x':'-14', 'y':'32'} );
+ textW.textContent = getNameWeek(2);
+ gElementContainer.appendChild(textW);
+ var textF = createElementSvg('text', {'x':'-14', 'y':'56'} );
+ textF.textContent = getNameWeek(4);
+ gElementContainer.appendChild(textF);
+ var textS = createElementSvg('text', {'x':'-14', 'y':'80'} );
+ textS.textContent = getNameWeek(6);
+ gElementContainer.appendChild(textS);
+
+ svgElement.appendChild(gElementContainer);
+
+ // Append Calendar to document;
+ $_this.append(svgElement);
+
+ fillData(massive);
+
+
+
+ function createElementSvg(type, prop ) {
+ var e = document.createElementNS('http://www.w3.org/2000/svg', type);
+ for (var p in prop) {
+ e.setAttribute(p, prop[p]);
+ }
+ return e;
+ }
+
+
+ function fillData(massive) {
+ var scoreCount = 0;
+ for (var m in massive) {
+ $_this.find('rect.day[data-date="' + massive[m].date + '"]').attr('data-count', massive[m].value);
+ $_this.find('rect.day[data-date="' + massive[m].date + '"]').attr('data-col', massive[m].col);
+ scoreCount += parseInt(massive[m].value);
+ }
+ $(settings.targetQuantity).text(massive.length + ' days, ' + scoreCount + ' scores');
+
+ }
+
+ function getNameMonth(a) {
+ return settings.months[a];
+ }
+ function getNameWeek(a) {
+ return settings.weeks[a];
+ }
+ function getBeautyDate(a) {
+ return getNameMonth(a.getMonth()) + ' ' + a.getDate() + ', ' + a.getFullYear();
+ }
+ function daysInMonth(d) {
+ return 32 - new Date(d.getFullYear(), d.getMonth(), 32).getDate();
+ }
+ };
+})(jQuery);
diff --git a/assets/js/sections/dayswithqso.js b/assets/js/sections/dayswithqso.js
index fc5061924..3a23b9d93 100644
--- a/assets/js/sections/dayswithqso.js
+++ b/assets/js/sections/dayswithqso.js
@@ -163,3 +163,32 @@ function months() {
}
});
}
+
+$(function() {
+ var pdata;
+ function render_punchcard() {
+ $.ajax({
+ url: base_url + 'index.php/dayswithqso/get_punchvals/' + $("#yr option:selected").val(),
+ success: function (data) {
+ pdata=data;
+
+ $('#js-glanceyear').empty().glanceyear(
+ pdata,
+ {
+ eventClick: function(e) {
+ $('#debug').html('Date: '+ e.date + ', Count: ' + e.count);
+ },
+ showToday: false,
+ today: new Date($("#yr option:selected").val() + '-12-31T01:00:00')
+ }
+
+ );
+ }
+ });
+ }
+
+ render_punchcard();
+ $("#yr").on('change',function(e) {
+ render_punchcard();
+ });
+});