Merge branch 'oams-instances-spotting' into 'master'

Extended spot details to capture multiple instances

See merge request gridtracker.org/gridtracker!214

If this is changing anything in the UI or operational behavior, please prepare to update the wiki!
merge-requests/217/head
Jonathan Angliss 2022-10-03 21:19:58 +00:00
commit 2c2547c81a
4 zmienionych plików z 87 dodań i 434 usunięć

Wyświetl plik

@ -32,4 +32,3 @@ careful when upgrading.
## Other Third Party routines
lib/third-party.js
lib/fw.js -- unused - fireworks when you complete WAS - from Henry N2VFL

Wyświetl plik

@ -1,314 +0,0 @@
function hooray()
{
var SCREEN_WIDTH = window.innerWidth,
SCREEN_HEIGHT = window.innerHeight,
mousePos = {
x: 400,
y: 300
},
// create canvas
canvas = document.createElement("canvas"),
context = canvas.getContext("2d"),
particles = [],
rockets = [],
MAX_PARTICLES = 400,
colorCode = 0;
// init
$(document).ready(function ()
{
document.body.appendChild(canvas);
canvas.width = SCREEN_WIDTH;
canvas.height = SCREEN_HEIGHT;
setInterval(launch, 800);
setInterval(loop, 1000 / 50);
});
// update mouse position
$(document).mousemove(function (e)
{
e.preventDefault();
mousePos = {
x: e.clientX,
y: e.clientY
};
});
// launch more rockets!!!
$(document).mousedown(function (e)
{
for (var i = 0; i < 5; i++)
{
launchFrom((Math.random() * SCREEN_WIDTH * 2) / 3 + SCREEN_WIDTH / 6);
}
});
function launch()
{
launchFrom(mousePos.x);
}
function launchFrom(x)
{
if (rockets.length < 10)
{
var rocket = new Rocket(x);
rocket.explosionColor = Math.floor((Math.random() * 360) / 10) * 10;
rocket.vel.y = Math.random() * -3 - 4;
rocket.vel.x = Math.random() * 6 - 3;
rocket.size = 8;
rocket.shrink = 0.999;
rocket.gravity = 0.01;
rockets.push(rocket);
}
}
function loop()
{
// update screen size
if (SCREEN_WIDTH != window.innerWidth)
{
canvas.width = SCREEN_WIDTH = window.innerWidth;
}
if (SCREEN_HEIGHT != window.innerHeight)
{
canvas.height = SCREEN_HEIGHT = window.innerHeight;
}
// clear canvas
context.fillStyle = "rgba(0, 0, 0, 0.05)";
context.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
var existingRockets = [];
for (var i = 0; i < rockets.length; i++)
{
// update and render
rockets[i].update();
rockets[i].render(context);
// calculate distance with Pythagoras
var distance = Math.sqrt(
Math.pow(mousePos.x - rockets[i].pos.x, 2) +
Math.pow(mousePos.y - rockets[i].pos.y, 2)
);
// random chance of 1% if rockets is above the middle
var randomChance =
rockets[i].pos.y < (SCREEN_HEIGHT * 2) / 3
? Math.random() * 100 <= 1
: false;
/* Explosion rules
- 80% of screen
- going down
- close to the mouse
- 1% chance of random explosion
*/
if (
rockets[i].pos.y < SCREEN_HEIGHT / 5 ||
rockets[i].vel.y >= 0 ||
distance < 50 ||
randomChance
)
{
rockets[i].explode();
}
else
{
existingRockets.push(rockets[i]);
}
}
rockets = existingRockets;
var existingParticles = [];
for (var i = 0; i < particles.length; i++)
{
particles[i].update();
// render and save particles that can be rendered
if (particles[i].exists())
{
particles[i].render(context);
existingParticles.push(particles[i]);
}
}
// update array with existing particles - old particles should be garbage collected
particles = existingParticles;
while (particles.length > MAX_PARTICLES)
{
particles.shift();
}
}
function Particle(pos)
{
this.pos = {
x: pos ? pos.x : 0,
y: pos ? pos.y : 0
};
this.vel = {
x: 0,
y: 0
};
this.shrink = 0.97;
this.size = 2;
this.resistance = 1;
this.gravity = 0;
this.flick = false;
this.alpha = 1;
this.fade = 0;
this.color = 0;
}
Particle.prototype.update = function ()
{
// apply resistance
this.vel.x *= this.resistance;
this.vel.y *= this.resistance;
// gravity down
this.vel.y += this.gravity;
// update position based on speed
this.pos.x += this.vel.x;
this.pos.y += this.vel.y;
// shrink
this.size *= this.shrink;
// fade out
this.alpha -= this.fade;
};
Particle.prototype.render = function (c)
{
if (!this.exists())
{
return;
}
c.save();
c.globalCompositeOperation = "lighter";
var x = this.pos.x,
y = this.pos.y,
r = this.size / 2;
var gradient = c.createRadialGradient(x, y, 0.1, x, y, r);
gradient.addColorStop(0.1, "rgba(255,255,255," + this.alpha + ")");
gradient.addColorStop(
0.8,
"hsla(" + this.color + ", 100%, 50%, " + this.alpha + ")"
);
gradient.addColorStop(1, "hsla(" + this.color + ", 100%, 50%, 0.1)");
c.fillStyle = gradient;
c.beginPath();
c.arc(
this.pos.x,
this.pos.y,
this.flick ? Math.random() * this.size : this.size,
0,
Math.PI * 2,
true
);
c.closePath();
c.fill();
c.restore();
};
Particle.prototype.exists = function ()
{
return this.alpha >= 0.1 && this.size >= 1;
};
function Rocket(x)
{
Particle.apply(this, [
{
x: x,
y: SCREEN_HEIGHT
}
]);
this.explosionColor = 0;
}
Rocket.prototype = new Particle();
Rocket.prototype.constructor = Rocket;
Rocket.prototype.explode = function ()
{
var count = Math.random() * 10 + 80;
for (var i = 0; i < count; i++)
{
var particle = new Particle(this.pos);
var angle = Math.random() * Math.PI * 2;
// emulate 3D effect by using cosine and put more particles in the middle
var speed = Math.cos((Math.random() * Math.PI) / 2) * 15;
particle.vel.x = Math.cos(angle) * speed;
particle.vel.y = Math.sin(angle) * speed;
particle.size = 10;
particle.gravity = 0.2;
particle.resistance = 0.92;
particle.shrink = Math.random() * 0.05 + 0.93;
particle.flick = true;
particle.color = this.explosionColor;
particles.push(particle);
}
};
Rocket.prototype.render = function (c)
{
if (!this.exists())
{
return;
}
c.save();
c.globalCompositeOperation = "lighter";
var x = this.pos.x,
y = this.pos.y,
r = this.size / 2;
var gradient = c.createRadialGradient(x, y, 0.1, x, y, r);
gradient.addColorStop(0.1, "rgba(255, 255, 255 ," + this.alpha + ")");
gradient.addColorStop(1, "rgba(0, 0, 0, " + this.alpha + ")");
c.fillStyle = gradient;
c.beginPath();
c.arc(
this.pos.x,
this.pos.y,
this.flick ? (Math.random() * this.size) / 2 + this.size / 2 : this.size,
0,
Math.PI * 2,
true
);
c.closePath();
c.fill();
c.restore();
};
}

Wyświetl plik

@ -6704,8 +6704,9 @@ function handleWsjtxStatus(newMessage)
Object.keys(g_spotCollector).length > 0
)
{
gtChatSendSpots(g_spotCollector);
gtChatSendSpots(g_spotCollector, g_spotDetailsCollector);
g_spotCollector = {};
g_spotDetailsCollector = {};
}
}
@ -6927,6 +6928,7 @@ function fitViewBetweenPoints(points, maxZoom = 20)
}
var g_spotCollector = {};
var g_spotDetailsCollector = {};
function handleWsjtxDecode(newMessage)
{
@ -7293,33 +7295,26 @@ function handleWsjtxDecode(newMessage)
g_lastTraffic.unshift(traffic);
g_lastTraffic.unshift(userTimeString(null));
g_lastTraffic.unshift(
"<hr style='border-color:#333;margin-top:0px;margin-bottom:2px;width:80%'>"
);
g_lastTraffic.unshift("<hr style='border-color:#333;margin-top:0px;margin-bottom:2px;width:80%'>");
drawTraffic();
lastMessageWasInfo = true;
}
if (
g_appSettings.gtSpotEnable === true &&
g_appSettings.gtSpotEnable === true &&
callsign.DEcall in g_gtCallsigns
)
if (g_appSettings.gtSpotEnable === true && callsign.DEcall in g_gtCallsigns)
{
if (
g_gtCallsigns[callsign.DEcall] in g_gtFlagPins &&
g_gtFlagPins[g_gtCallsigns[callsign.DEcall]].o == 1
) { g_spotCollector[g_gtCallsigns[callsign.DEcall]] = callsign.RSTsent; }
let key = g_gtCallsigns[callsign.DEcall];
if (key in g_gtFlagPins && g_gtFlagPins[key].o == 1)
{
g_spotCollector[key] = callsign.RSTsent;
g_spotDetailsCollector[key] = [callsign.delta + newMessage.OF, callsign.mode];
}
}
}
if (callsign.dxcc != -1) countryName = g_dxccToAltName[callsign.dxcc];
if (canPath == true)
{
if (
callsign.DXcall.indexOf("CQ") < 0 &&
g_appSettings.gridViewMode != 2
)
if (callsign.DXcall.indexOf("CQ") < 0 && g_appSettings.gridViewMode != 2)
{
// Nothing special, we know the callers grid
if (callsign.grid != "")
@ -7327,13 +7322,9 @@ function handleWsjtxDecode(newMessage)
// Our msgDEcallsign is not sending a CQ.
// Let's see if we can locate who he's talking to in our known list
var DEcallsign = null;
if (
callsign.DXcall + newMessage.OB + newMessage.OM in
g_liveCallsigns
)
if (callsign.DXcall + newMessage.OB + newMessage.OM in g_liveCallsigns)
{
DEcallsign =
g_liveCallsigns[callsign.DXcall + newMessage.OB + newMessage.OM];
DEcallsign = g_liveCallsigns[callsign.DXcall + newMessage.OB + newMessage.OM];
}
else if (callsign.DXcall in g_liveCallsigns)
{
@ -7385,11 +7376,7 @@ function handleWsjtxDecode(newMessage)
}
}
}
else if (
g_mapSettings.qrzDxccFallback &&
msgDXcallsign == myDEcall &&
callsign.dxcc > 0
)
else if (g_mapSettings.qrzDxccFallback && msgDXcallsign == myDEcall && callsign.dxcc > 0)
{
// the caller is calling us, but they don't have a grid, so lookup the DXCC and show it
var strokeColor = getQrzPathColor();
@ -7447,13 +7434,7 @@ function handleWsjtxDecode(newMessage)
}
}
}
else if (
g_mapSettings.CQhilite &&
msgDXcallsign.indexOf("CQ ") == 0 &&
callsign.grid != "" &&
g_appSettings.gridViewMode != 2 &&
pathWidthValue.value != 0
)
else if (g_mapSettings.CQhilite && msgDXcallsign.indexOf("CQ ") == 0 && callsign.grid != "" && g_appSettings.gridViewMode != 2 && pathWidthValue.value != 0)
{
var CCd = msgDXcallsign.replace("CQ ", "").split(" ")[0];
if (CCd.length < 5 && !(CCd in g_pathIgnore))
@ -7611,14 +7592,15 @@ function shapeFeature(
feature.size = 2;
return feature;
}
function handleWsjtxClear(newMessage)
{
for (var hash in g_liveCallsigns)
{
if (
g_liveCallsigns[hash].instance == newMessage.instance ||
g_liveCallsigns[hash].mode == g_instances[newMessage.instance].status.MO
) { delete g_liveCallsigns[hash]; }
if (g_liveCallsigns[hash].instance == newMessage.instance || g_liveCallsigns[hash].mode == g_instances[newMessage.instance].status.MO)
{
delete g_liveCallsigns[hash];
}
}
for (var call in g_callRoster)
{
@ -7634,8 +7616,8 @@ function handleWsjtxClear(newMessage)
function goProcessRoster(isRealtime = false)
{
var now = timeNowSec();
for (var call in g_callRoster)
let now = timeNowSec();
for (const call in g_callRoster)
{
if (now - g_callRoster[call].callObj.age > 300)
{
@ -7665,10 +7647,7 @@ function goProcessRoster(isRealtime = false)
function handleClosed(newMessage)
{
if (
g_activeInstance == newMessage.Id &&
g_instances[newMessage.Id].open == false
)
if (g_activeInstance == newMessage.Id && g_instances[newMessage.Id].open == false)
{
txrxdec.style.backgroundColor = "Purple";
txrxdec.style.borderColor = "Purple";
@ -7747,9 +7726,7 @@ function setCenterQTH()
{
g_appSettings.centerGridsquare = homeQTHInput.value;
// Grab home QTH Gridsquare from Center QTH
var LL = squareToLatLong(homeQTHInput.value);
// panTo(ol.proj.fromLonLat([LL.lo2 - (LL.lo2 - LL.lo1) / 2, LL.la2 - ((LL.la2 - LL.la1) / 2)]));
let LL = squareToLatLong(homeQTHInput.value);
g_map
.getView()
@ -8866,16 +8843,9 @@ function showDXCCsBox()
Object.keys(List).forEach(function (key, i)
{
var band =
g_appSettings.gtBandFilter == "auto"
? myBand
: g_appSettings.gtBandFilter.length == 0
? ""
: g_appSettings.gtBandFilter;
var band = g_appSettings.gtBandFilter == "auto" ? myBand : g_appSettings.gtBandFilter.length == 0 ? "" : g_appSettings.gtBandFilter;
var unconfirmedCallsKey = new UnconfirmedCallsKey(List[key].dxcc, band);
if (g_unconfirmedCalls.has(unconfirmedCallsKey.key) &&
g_unconfirmedCalls.get(unconfirmedCallsKey.key) != unconfirmedCallsSentinel
)
if (g_unconfirmedCalls.has(unconfirmedCallsKey.key) && g_unconfirmedCalls.get(unconfirmedCallsKey.key) != unconfirmedCallsSentinel)
{
var onMousedown = function (e)
{
@ -9030,21 +9000,11 @@ function displayItemList(table, color)
function showWPXBox()
{
var worker = getCurrentBandModeHTML();
var band =
g_appSettings.gtBandFilter == "auto"
? myBand
: g_appSettings.gtBandFilter.length == 0
? ""
: g_appSettings.gtBandFilter;
var mode =
g_appSettings.gtModeFilter == "auto"
? myMode
: g_appSettings.gtModeFilter.length == 0
? ""
: g_appSettings.gtModeFilter;
var band = g_appSettings.gtBandFilter == "auto" ? myBand : g_appSettings.gtBandFilter.length == 0 ? "" : g_appSettings.gtBandFilter;
var mode = g_appSettings.gtModeFilter == "auto" ? myMode : g_appSettings.gtModeFilter.length == 0 ? "" : g_appSettings.gtModeFilter;
if (mode == "Digital") mode = "dg";
if (mode == "Phone") mode = "ph";
if (mode == "Digital") { mode = "dg"; }
if (mode == "Phone") { mode = "ph"; }
var modifier = String(band) + String(mode);
var worked = 0;
@ -9054,10 +9014,7 @@ function showWPXBox()
for (var key in g_tracker.worked.px)
{
if (
typeof g_tracker.worked.px[key] == "string" &&
key + modifier in g_tracker.worked.px
)
if (typeof g_tracker.worked.px[key] == "string" && key + modifier in g_tracker.worked.px)
{
List[key] = key;
}
@ -9065,10 +9022,7 @@ function showWPXBox()
for (var key in g_tracker.confirmed.px)
{
if (
typeof g_tracker.confirmed.px[key] == "string" &&
key + modifier in g_tracker.confirmed.px
)
if (typeof g_tracker.confirmed.px[key] == "string" && key + modifier in g_tracker.confirmed.px)
{
ListConfirmed[key] = key;
}
@ -16096,47 +16050,43 @@ function pskSpotResults(buffer, flag)
var g_oamsSpotTimeout = null;
function addNewOAMSSpot(cid, db)
function addNewOAMSSpot(cid, db, frequency, band, mode)
{
if (cid in g_gtFlagPins)
if (g_oamsSpotTimeout !== null)
{
if (g_oamsSpotTimeout !== null)
{
nodeTimers.clearTimeout(g_oamsSpotTimeout);
g_oamsSpotTimeout = null;
}
var report;
var call = g_gtFlagPins[cid].call;
var mode = g_gtFlagPins[cid].mode;
var grid = g_gtFlagPins[cid].grid.substr(0, 6);
var band = g_gtFlagPins[cid].band;
var hash = call + mode + band + grid.substr(0, 4);
if (hash in g_receptionReports.spots)
{
report = g_receptionReports.spots[hash];
}
else
{
report = g_receptionReports.spots[hash] = {};
report.call = call;
report.band = band;
report.grid = grid;
report.mode = mode;
}
report.dxcc = g_gtFlagPins[cid].dxcc;
report.when = timeNowSec();
report.snr = Number(db);
report.freq = g_gtFlagPins[cid].freq;
var SNR = parseInt((parseInt(report.snr) + 25) * 9);
if (SNR > 255) SNR = 255;
if (SNR < 0) SNR = 0;
report.color = SNR;
g_oamsSpotTimeout = nodeTimers.setTimeout(redrawSpots, 500);
nodeTimers.clearTimeout(g_oamsSpotTimeout);
g_oamsSpotTimeout = null;
}
let report;
let call = g_gtFlagPins[cid].call;
let grid = g_gtFlagPins[cid].grid.substr(0, 6);
let hash = call + mode + band + grid.substr(0, 4);
if (hash in g_receptionReports.spots)
{
report = g_receptionReports.spots[hash];
}
else
{
report = g_receptionReports.spots[hash] = {};
report.call = call;
report.band = band;
report.grid = grid;
report.mode = mode;
}
report.dxcc = g_gtFlagPins[cid].dxcc;
report.when = timeNowSec();
report.snr = Number(db);
report.freq = frequency;
let SNR = parseInt((parseInt(report.snr) + 25) * 9);
if (SNR > 255) SNR = 255;
if (SNR < 0) SNR = 0;
report.color = SNR;
g_oamsSpotTimeout = nodeTimers.setTimeout(redrawSpots, 250);
}
function spotFeature(center)

Wyświetl plik

@ -249,12 +249,13 @@ function gtChatSendStatus()
}
}
function gtChatSendSpots(spotsObject)
function gtChatSendSpots(spotsObject, detailsObject)
{
var msg = Object();
msg.type = "o";
msg.uuid = g_appSettings.chatUUID;
msg.o = spotsObject;
msg.d = detailsObject;
msg = JSON.stringify(msg);
sendGtJson(msg);
}
@ -603,7 +604,24 @@ function gtChatStateMachine()
function gtSpotMessage(jsmesg)
{
addNewOAMSSpot(jsmesg.cid, jsmesg.db);
if (jsmesg.cid in g_gtFlagPins)
{
let frequency, band, mode;
if (jsmesg.ex != null)
{
frequency = Number(jsmesg.ex[0]);
band = Number(frequency / 1000000).formatBand();
mode = String(jsmesg.ex[1]);
}
else
{
frequency = g_gtFlagPins[jsmesg.cid].freq;
band = g_gtFlagPins[jsmesg.cid].band;
mode = g_gtFlagPins[jsmesg.cid].mode;
}
addNewOAMSSpot(jsmesg.cid, jsmesg.db, frequency, band, mode);
}
}
function gtLightningStrike(jsmesg)