182 lines
4.4 KiB
JavaScript
182 lines
4.4 KiB
JavaScript
/*
|
|
Copyright (c) 2023-forever Douglas Malnati. All rights reserved.
|
|
|
|
See the /faq/tos page for details.
|
|
|
|
(If this generated header is stamped on a file which is a 3rd party file or under a different license or copyright, then ignore this copyright statement and use that file's terms.)
|
|
*/
|
|
|
|
import * as utl from '/js/Utl.js';
|
|
|
|
import { Base } from './Base.js';
|
|
import { TabularData } from '../../../../js/TabularData.js';
|
|
|
|
|
|
|
|
export class WsprSearchUiFlightStatsController
|
|
extends Base
|
|
{
|
|
constructor(cfg)
|
|
{
|
|
super();
|
|
|
|
this.cfg = cfg;
|
|
|
|
this.ok = this.cfg.container;
|
|
|
|
if (this.ok)
|
|
{
|
|
this.ui = this.#MakeUI();
|
|
this.cfg.container.appendChild(this.ui);
|
|
}
|
|
}
|
|
|
|
SetDebug(tf)
|
|
{
|
|
super.SetDebug(tf);
|
|
|
|
this.t.SetCcGlobal(tf);
|
|
}
|
|
|
|
OnEvent(evt)
|
|
{
|
|
if (this.ok)
|
|
{
|
|
switch (evt.type) {
|
|
case "DATA_TABLE_RAW_READY": this.#OnDataTableRawReady(evt); break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#OnDataTableRawReady(evt)
|
|
{
|
|
this.t.Reset();
|
|
this.t.Event(`WsprSearchUiFlightStatsController::OnDataTableRawReady Start`);
|
|
|
|
// clear existing child nodes
|
|
this.cfg.container.innerHTML = "";
|
|
|
|
// get handle to data
|
|
let td = evt.tabularDataReadOnly;
|
|
|
|
// calculate distance stats
|
|
let distKm = 0;
|
|
let distMi = 0;
|
|
|
|
td.ForEach((row) => {
|
|
distKm += td.Get(row, "DistKm");
|
|
distMi += td.Get(row, "DistMi");
|
|
});
|
|
|
|
// calculate spot stats
|
|
let spotCount = td.GetDataTable().length - 1;
|
|
|
|
// calculate duration stats
|
|
let durationStr = "";
|
|
if (td.Length() > 1)
|
|
{
|
|
let dtFirst = td.Get(td.Length() - 1, "DateTimeLocal");
|
|
let dtLast = td.Get(0, "DateTimeLocal");
|
|
|
|
let msFirst = utl.ParseTimeToMs(dtFirst);
|
|
let msLast = utl.ParseTimeToMs(dtLast);
|
|
|
|
let msDiff = msLast - msFirst;
|
|
durationStr = utl.MsToDurationStrDaysHoursMinutes(msDiff);
|
|
}
|
|
|
|
// calculate eastward laps around world using resolved location
|
|
let lapCount = this.#CalculateEastwardLapCount(td);
|
|
|
|
// create summary
|
|
let status =
|
|
`
|
|
Flight duration: ${durationStr}
|
|
<br/>
|
|
<br/>
|
|
Laps around world: ${utl.Commas(lapCount)}
|
|
<br/>
|
|
<br/>
|
|
Distance Traveled Km: ${utl.Commas(Math.round(distKm))}
|
|
<br/>
|
|
Distance Traveled Mi: ${utl.Commas(Math.round(distMi))}
|
|
<br/>
|
|
<br/>
|
|
Spots: ${utl.Commas(spotCount)}
|
|
`;
|
|
|
|
// update UI
|
|
this.ui.innerHTML = status;
|
|
|
|
// replace with new
|
|
this.cfg.container.appendChild(this.ui);
|
|
|
|
this.t.Event(`WsprSearchUiFlightStatsController::OnDataTableRawReady End`);
|
|
}
|
|
|
|
#MakeUI()
|
|
{
|
|
this.ui = document.createElement('div');
|
|
|
|
return this.ui;
|
|
}
|
|
|
|
#CalculateEastwardLapCount(td)
|
|
{
|
|
let lonList = [];
|
|
|
|
// Table is newest-first, so iterate oldest -> newest.
|
|
for (let idx = td.Length() - 1; idx >= 0; --idx)
|
|
{
|
|
let lon = td.Get(idx, "Lng");
|
|
if (lon == undefined || lon == null || lon === "")
|
|
{
|
|
continue;
|
|
}
|
|
|
|
lon = Number(lon);
|
|
if (Number.isFinite(lon))
|
|
{
|
|
lonList.push(lon);
|
|
}
|
|
}
|
|
|
|
if (lonList.length < 2)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// Unwrap longitude so east/west movement is continuous across +/-180.
|
|
let unwrappedLonList = [lonList[0]];
|
|
for (let i = 1; i < lonList.length; ++i)
|
|
{
|
|
let prevRaw = lonList[i - 1];
|
|
let curRaw = lonList[i];
|
|
|
|
let delta = curRaw - prevRaw;
|
|
if (delta > 180) { delta -= 360; }
|
|
if (delta < -180) { delta += 360; }
|
|
|
|
let nextUnwrapped = unwrappedLonList[unwrappedLonList.length - 1] + delta;
|
|
unwrappedLonList.push(nextUnwrapped);
|
|
}
|
|
|
|
let startLon = unwrappedLonList[0];
|
|
let lapCount = 0;
|
|
|
|
// Count only eastward full wraps past start + 360n.
|
|
for (let i = 1; i < unwrappedLonList.length; ++i)
|
|
{
|
|
let prevRel = unwrappedLonList[i - 1] - startLon;
|
|
let curRel = unwrappedLonList[i] - startLon;
|
|
|
|
while (prevRel < (lapCount + 1) * 360 && curRel >= (lapCount + 1) * 360)
|
|
{
|
|
++lapCount;
|
|
}
|
|
}
|
|
|
|
return lapCount;
|
|
}
|
|
}
|