mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2026-04-30 02:35:57 +00:00
DX stats table. Closes #99
This commit is contained in:
@@ -15,6 +15,7 @@ info:
|
||||
|
||||
### 1.2
|
||||
|
||||
* Added `/dxstats` endpoint for inter-continent DX spot statistics.
|
||||
* Added `/solar` endpoint for solar and propagation conditions.
|
||||
* Added `solar_condition_providers` array to the `/status` response.
|
||||
|
||||
@@ -406,6 +407,61 @@ paths:
|
||||
$ref: '#/components/schemas/AlertStream'
|
||||
|
||||
|
||||
/solar:
|
||||
get:
|
||||
tags:
|
||||
- Propagation & DX
|
||||
summary: Get solar and band conditions
|
||||
description: Returns the current solar conditions and HF/VHF propagation condition summaries. This data is sourced from external providers (e.g. HamQSL) and updated periodically. All fields may be null if no provider has successfully fetched data yet.
|
||||
operationId: solar
|
||||
responses:
|
||||
'200':
|
||||
description: Success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SolarConditions'
|
||||
|
||||
|
||||
/dxstats:
|
||||
get:
|
||||
tags:
|
||||
- Propagation & DX
|
||||
summary: Get spot counts by continent and band
|
||||
description: Returns a three-level nested object of spot counts from the current spot database, grouped by DE continent, then DX continent, then band. Only spots in the last hour are counted, regardless of what the server owner has set the spot expiry time to.
|
||||
operationId: dxstats
|
||||
responses:
|
||||
'200':
|
||||
description: Success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
description: Spot counts keyed by DE continent
|
||||
additionalProperties:
|
||||
type: object
|
||||
description: Spot counts keyed by DX continent
|
||||
additionalProperties:
|
||||
type: object
|
||||
description: Spot counts keyed by band
|
||||
properties:
|
||||
160m: { type: integer }
|
||||
80m: { type: integer }
|
||||
60m: { type: integer }
|
||||
40m: { type: integer }
|
||||
30m: { type: integer }
|
||||
20m: { type: integer }
|
||||
17m: { type: integer }
|
||||
15m: { type: integer }
|
||||
12m: { type: integer }
|
||||
10m: { type: integer }
|
||||
6m: { type: integer }
|
||||
example:
|
||||
EU:
|
||||
NA: { 20m: 42, 17m: 7, 15m: 3, 10m: 0, 6m: 0, 160m: 0, 80m: 1, 60m: 0, 40m: 5, 30m: 2, 12m: 0 }
|
||||
EU: { 20m: 18, 17m: 2, 15m: 0, 10m: 0, 6m: 1, 160m: 0, 80m: 4, 60m: 0, 40m: 9, 30m: 1, 12m: 0 }
|
||||
|
||||
|
||||
/status:
|
||||
get:
|
||||
tags:
|
||||
@@ -781,23 +837,6 @@ paths:
|
||||
type: string
|
||||
example: "Failed"
|
||||
|
||||
|
||||
/solar:
|
||||
get:
|
||||
tags:
|
||||
- General
|
||||
summary: Get solar and propagation conditions
|
||||
description: Returns the current solar conditions and HF/VHF propagation condition summaries. This data is sourced from external providers (e.g. HamQSL) and updated periodically. All fields may be null if no provider has successfully fetched data yet.
|
||||
operationId: solar
|
||||
responses:
|
||||
'200':
|
||||
description: Success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SolarConditions'
|
||||
|
||||
|
||||
components:
|
||||
schemas:
|
||||
Source:
|
||||
@@ -1177,7 +1216,7 @@ components:
|
||||
SpotStream:
|
||||
type: object
|
||||
description: A server-sent event containing a spot
|
||||
required: [data]
|
||||
required: [ data ]
|
||||
properties:
|
||||
data:
|
||||
$ref: "#/components/schemas/Spot"
|
||||
@@ -1278,7 +1317,7 @@ components:
|
||||
AlertStream:
|
||||
type: object
|
||||
description: A server-sent event containing an alert
|
||||
required: [data]
|
||||
required: [ data ]
|
||||
properties:
|
||||
data:
|
||||
$ref: "#/components/schemas/Alert"
|
||||
@@ -1422,28 +1461,28 @@ components:
|
||||
properties:
|
||||
80m-40m-day:
|
||||
type: string
|
||||
enum: [Good, Fair, Poor]
|
||||
enum: [ Good, Fair, Poor ]
|
||||
80m-40m-night:
|
||||
type: string
|
||||
enum: [Good, Fair, Poor]
|
||||
enum: [ Good, Fair, Poor ]
|
||||
30m-20m-day:
|
||||
type: string
|
||||
enum: [Good, Fair, Poor]
|
||||
enum: [ Good, Fair, Poor ]
|
||||
30m-20m-night:
|
||||
type: string
|
||||
enum: [Good, Fair, Poor]
|
||||
enum: [ Good, Fair, Poor ]
|
||||
17m-15m-day:
|
||||
type: string
|
||||
enum: [Good, Fair, Poor]
|
||||
enum: [ Good, Fair, Poor ]
|
||||
17m-15m-night:
|
||||
type: string
|
||||
enum: [Good, Fair, Poor]
|
||||
enum: [ Good, Fair, Poor ]
|
||||
12m-10m-day:
|
||||
type: string
|
||||
enum: [Good, Fair, Poor]
|
||||
enum: [ Good, Fair, Poor ]
|
||||
12m-10m-night:
|
||||
type: string
|
||||
enum: [Good, Fair, Poor]
|
||||
enum: [ Good, Fair, Poor ]
|
||||
vhf_conditions:
|
||||
type: object
|
||||
description: VHF propagation condition assessments, keyed by condition name
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// Cache for the full dxstats API response, so we can reload on the fly if the user changes the value of their continent
|
||||
// in the select box
|
||||
let dxStatsData = null;
|
||||
|
||||
// Load solar conditions
|
||||
function loadSolarConditions() {
|
||||
$.getJSON('/api/v1/solar', function(jsonData) {
|
||||
@@ -104,7 +108,61 @@ function loadSolarConditions() {
|
||||
});
|
||||
}
|
||||
|
||||
// Take a normalised number 0-1 and generate a background colour for the DX stats cells
|
||||
function dxStatsColor(t) {
|
||||
const yellow = [255, 243, 205];
|
||||
const green = [209, 231, 221];
|
||||
if (t == 0.0) {
|
||||
return "rgb(248, 215, 218)";
|
||||
} else {
|
||||
const ch = (i) => Math.round(yellow[i] + (green[i] - yellow[i]) * t);
|
||||
return `rgb(${ch(0)}, ${ch(1)}, ${ch(2)})`;
|
||||
}
|
||||
}
|
||||
|
||||
// Render the DX stats table for the currently selected DE continent
|
||||
function renderDxStats() {
|
||||
if (!dxStatsData) { return; }
|
||||
const deContinent = $('#dxstats-de-continent').val();
|
||||
const deData = dxStatsData[deContinent];
|
||||
if (!deData) { return; }
|
||||
|
||||
const cells = [];
|
||||
Object.entries(deData).forEach(function([dxContinent, bands]) {
|
||||
Object.entries(bands).forEach(function([band, count]) {
|
||||
const cell = $('#dxstats-' + dxContinent + '-' + band);
|
||||
cell.text(count);
|
||||
cells.push({ cell, count });
|
||||
});
|
||||
});
|
||||
|
||||
const counts = cells.map(function(c) { return c.count; });
|
||||
const min = Math.min(...counts);
|
||||
const max = Math.max(...counts);
|
||||
const range = max - min;
|
||||
cells.forEach(function({ cell, count }) {
|
||||
const t = range > 0 ? (count - min) / range : 0;
|
||||
cell.css('background-color', dxStatsColor(t));
|
||||
});
|
||||
}
|
||||
|
||||
// Called when the DE continent select changes
|
||||
function dxStatsContientChanged() {
|
||||
saveSettings();
|
||||
renderDxStats();
|
||||
}
|
||||
|
||||
// Fetch DX stats from the API and render
|
||||
function loadDxStats() {
|
||||
$.getJSON('/api/v1/dxstats', function(jsonData) {
|
||||
dxStatsData = jsonData;
|
||||
renderDxStats();
|
||||
});
|
||||
}
|
||||
|
||||
// Startup
|
||||
$(document).ready(function() {
|
||||
loadSettings();
|
||||
loadSolarConditions();
|
||||
loadDxStats();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user