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