From 198389a764bc8d59a8ca218c96043190d2779c9b Mon Sep 17 00:00:00 2001
From: Andreas <6977712+AndreasK79@users.noreply.github.com>
Date: Thu, 20 Jul 2023 21:42:45 +0200
Subject: [PATCH] [Bandmap] First integration of bandmap from @int2001
---
application/controllers/Bandmap.php | 23 +++
application/language/english/menu_lang.php | 1 +
application/language/german/menu_lang.php | 1 +
application/views/bandmap/index.php | 12 ++
application/views/interface_assets/footer.php | 9 +
application/views/interface_assets/header.php | 12 +-
assets/css/general.css | 50 ++++++
assets/js/sections/bandmap.js | 166 ++++++++++++++++++
8 files changed, 269 insertions(+), 5 deletions(-)
create mode 100644 application/controllers/Bandmap.php
create mode 100644 application/views/bandmap/index.php
create mode 100644 assets/js/sections/bandmap.js
diff --git a/application/controllers/Bandmap.php b/application/controllers/Bandmap.php
new file mode 100644
index 00000000..62c19b90
--- /dev/null
+++ b/application/controllers/Bandmap.php
@@ -0,0 +1,23 @@
+load->model('user_model');
+ if(!$this->user_model->authorize(2)) { $this->session->set_flashdata('notice', 'You\'re not allowed to do that!'); redirect('dashboard'); }
+ }
+
+ function index() {
+ $footerData = [];
+ $footerData['scripts'] = [
+ 'assets/js/sections/bandmap.js',
+ ];
+
+ $data['page_title'] = "Bandmap";
+ $this->load->view('interface_assets/header', $data);
+ $this->load->view('bandmap/index');
+ $this->load->view('interface_assets/footer', $footerData);
+ }
+}
diff --git a/application/language/english/menu_lang.php b/application/language/english/menu_lang.php
index b4951a41..7b72a7f6 100644
--- a/application/language/english/menu_lang.php
+++ b/application/language/english/menu_lang.php
@@ -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';
diff --git a/application/language/german/menu_lang.php b/application/language/german/menu_lang.php
index 05fbb07d..1efedc0a 100644
--- a/application/language/german/menu_lang.php
+++ b/application/language/german/menu_lang.php
@@ -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';
diff --git a/application/views/bandmap/index.php b/application/views/bandmap/index.php
new file mode 100644
index 00000000..2561c811
--- /dev/null
+++ b/application/views/bandmap/index.php
@@ -0,0 +1,12 @@
+
diff --git a/application/views/interface_assets/footer.php b/application/views/interface_assets/footer.php
index db2d2fb2..030f28a0 100644
--- a/application/views/interface_assets/footer.php
+++ b/application/views/interface_assets/footer.php
@@ -2911,6 +2911,15 @@ function viewEqsl(picture, callsign) {
+uri->segment(1) == "bandmap") { ?>
+
+
+
+
+
+
+
+
uri->segment(1) == "awards") {
// Get Date format
if($this->session->userdata('user_date_format')) {
diff --git a/application/views/interface_assets/header.php b/application/views/interface_assets/header.php
index df346f2b..6166f617 100644
--- a/application/views/interface_assets/header.php
+++ b/application/views/interface_assets/header.php
@@ -81,6 +81,8 @@
+
+
@@ -179,7 +181,7 @@
-
+
@@ -282,8 +284,8 @@ $oqrs_requests = $CI->oqrs_model->oqrs_requests($location_list);
-
- oqrs_model->oqrs_requests($location_list);
Extras
-
+
diff --git a/assets/css/general.css b/assets/css/general.css
index 70bfbfa1..50f6f767 100644
--- a/assets/css/general.css
+++ b/assets/css/general.css
@@ -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;
+}
\ No newline at end of file
diff --git a/assets/js/sections/bandmap.js b/assets/js/sections/bandmap.js
new file mode 100644
index 00000000..91ee9429
--- /dev/null
+++ b/assets/js/sections/bandmap.js
@@ -0,0 +1,166 @@
+$(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 dxcluster_provider = 'https://dxc.jo30.de/dxcache';
+ 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: '{chartTitle}
' +
+ '{typeDescription}
' +
+ '{chartSubtitle}
' +
+ '{chartLongdesc}
' +
+ '{viewTableButton}
'
+ },
+ point: {
+ valueDescriptionFormat: '{index}. {point.label}. {point.description}.'
+ }
+ },
+ xAxis: {
+ 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(lowerQrg,upperQrg,maxAgeMinutes) {
+ $.ajax({
+ url: dxcluster_provider + "/spots",
+ cache: false,
+ dataType: "json"
+ }).done(function(dxspots) {
+ spots4chart=[];
+ dxspots.sort(SortByQrg);
+ dxspots=reduce_spots(dxspots);
+ dxspots.forEach((single) => {
+ if ( (single.frequency >= lowerQrg) && (single.frequency <= upperQrg) && (Date.parse(single.when)>(Date.now() - 1000 * 60 * maxAgeMinutes)) ) {
+ spots4chart.push(convert2high(single));
+ }
+ });
+ // console.log(spots4chart);
+ bandMapChart.series[0].setData(spots4chart);
+ bandMapChart.redraw();
+ });
+ }
+
+
+ function set_chart(lowerQrg,upperQrg,maxAgeMinutes) {
+ $.ajax({
+ url: dxcluster_provider + "/spots",
+ cache: false,
+ dataType: "json"
+ }).done(function(dxspots) {
+ spots4chart=[];
+ dxspots.sort(SortByQrg);
+ dxspots=reduce_spots(dxspots);
+ dxspots.forEach((single) => {
+ if ( (single.frequency >= lowerQrg) && (single.frequency <= upperQrg) && (Date.parse(single.when)>(Date.now() - 1000 * 60 * maxAgeMinutes)) ) {
+ spots4chart.push(convert2high(single));
+ }
+ });
+ bandMapChart=render_chart('20m',spots4chart);
+ });
+ }
+
+ set_chart(14000,14350,30);
+ setInterval(function () { update_chart(14000,14350,30); },60000);
+});