Punchcard / DRAFT

This commit is contained in:
int2001
2024-12-06 09:41:07 +00:00
parent 38292864bb
commit 45d38f546e
5 changed files with 351 additions and 40 deletions

View File

@@ -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);
}
}

View File

@@ -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)
*/

View File

@@ -22,6 +22,9 @@
<li class="nav-item">
<a class="nav-link" id="streaks-tab" data-bs-toggle="tab" href="#streaks" role="tab" aria-controls="streaks" aria-selected="false"><?= __("Streaks"); ?></a>
</li>
<li class="nav-item">
<a class="nav-link" id="punchcard-tab" data-bs-toggle="tab" href="#punchcard" role="tab" aria-controls="punchcard" aria-selected="false"><?= __("QSOs of Year"); ?></a>
</li>
</ul>
</div>
@@ -64,12 +67,45 @@
<canvas id="weekdaysChart" width="400" height="150"></canvas>
</div>
<div class="tab-pane fade" id="monthsofyear" role="tabpanel" aria-labelledby="monthsofyear-tab">
<div class="tab-pane fade" id="monthsofyear" role="tabpanel" aria-labelledby="monthsofyear-tab">
<br/>
<h3><?= __('QSOs breakdown by month of the year'); ?></h3>
<canvas id="monthChart" width="400" height="150"></canvas>
</div>
<div class="tab-pane fade" id="punchcard" role="tabpanel" aria-labelledby="punchcard-tab">
<link rel="stylesheet" href="/assets/css/glanceyear.css">
<br/>
<select class="form-select form-select-sm me-2 w-auto" id="yr" name="yr">
<?php
foreach($years as $yr) {
echo '<option value="'.$yr.'">'.__("Year")." ".$yr.'</option>';
}
?>
</select>
<div class="glanceyear-container">
<h1 class="glanceyear-header">QSOs this Year
<span class="glanceyear-quantity"></span>
</h1>
<div class="glanceyear-content" id="js-glanceyear">
</div>
<div class="glanceyear-summary">
<div class="glanceyear-legend">
Less&nbsp;
<span style="background-color: #eee"></span>
<span style="background-color: #c3dbda"></span>
<span style="background-color: #5caeaa"></span>
<span style="background-color: #277672"></span>
&nbsp;More
</div>
Calendar with QSOs <br>
<span id="debug"></span>
</div>
</div>
</div>
<div class="tab-pane fade" id="streaks" role="tabpanel" aria-labelledby="streaks-tab">
<br/>
<h2><?= __("Longest streak with QSOs in the log"); ?></h2>
@@ -161,5 +197,6 @@
}
?>
</div>
</div>
</div>

View File

@@ -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 = $('<div>')
.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( '<b>' + tagCount + '</b> 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);

View File

@@ -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();
});
});