diff --git a/html/index.html b/html/index.html index 1a060cb..a7f6339 100644 --- a/html/index.html +++ b/html/index.html @@ -7,6 +7,7 @@ + diff --git a/html/js/board.js b/html/js/board.js index 1a8394b..42fbeff 100644 --- a/html/js/board.js +++ b/html/js/board.js @@ -2,46 +2,13 @@ import { ReconnectingWebSocket } from "./reconnecting-websocket.min.js"; import { ActivityIcon } from "./activity_icon.min.js"; import { StatsBox } from "./statsbox.min.js"; import { InfoBox } from "./infobox.min.js"; +import { distance3, trimPrefix, makeTd, addRow, whatGame } from "./utils.min.js"; /* https://github.com/HansAcker/EDDN-RealTime */ // TODO: modularize -// TODO: move to inevitable utility module - -// const distanceN = (v0, v1) => Math.hypot.apply(null, v0.map((v, i) => v - v1[i])); -const distance3 = (v0, v1) => Math.hypot(v0[0] - v1[0], v0[1] - v1[1], v0[2] - v1[2]); // subtract vectors, return length -const trimPrefix = (str, prefix) => (str.startsWith(prefix) ? str.slice(prefix.length) : str).trim(); -const makeTd = (textContent) => { const td = document.createElement("td"); td.textContent = td.title = textContent; return td; }; - -function addRow(tbody, tr) { - while (tbody.childElementCount >= listLength) { - tbody.lastElementChild.remove(); - } - - tbody.prepend(tr); -} - -function whatGame(data) { - try { - // no decision if gameversion is not set or set to CAPI- - // https://github.com/EDCD/EDDN/blob/live/docs/Developers.md#gameversions-and-gamebuild - const gameversion = data.header.gameversion; - if (gameversion && (gameversion.startsWith("CAPI-Legacy-") || parseInt(gameversion) < 4)) { - return "Legacy"; - } - - // https://github.com/EDCD/EDDN/blob/live/docs/Developers.md#horizons-and-odyssey-flags - const msg = data.message; - return msg.odyssey ? "Odyssey" : msg.horizons ? "Horizons" : msg.horizons === false ? "Base" : "Unknown"; - } catch(error) { - console.log("gameversion error:", error); - return "Unknown"; - } -} - - const gameStats = new StatsBox(statstable.querySelector("tbody"), { "Total": 0, "Old": 0, diff --git a/html/js/board.min.js b/html/js/board.min.js index a29bd2d..65b086c 100644 --- a/html/js/board.min.js +++ b/html/js/board.min.js @@ -1 +1 @@ -import{ReconnectingWebSocket as e}from"./reconnecting-websocket.min.js";import{ActivityIcon as t}from"./activity_icon.min.js";import{StatsBox as o}from"./statsbox.min.js";import{InfoBox as n}from"./infobox.min.js";const d=(e,t)=>Math.hypot(e[0]-t[0],e[1]-t[1],e[2]-t[2]),m=e=>{var t=document.createElement("td");return t.textContent=t.title=e,t};function u(e,t){for(;e.childElementCount>=listLength;)e.lastElementChild.remove();e.prepend(t)}const f=new o(statstable.querySelector("tbody"),{Total:0,Old:0,New:0,Ignored:0,Taxi:0,Base:0,Horizons:0,Odyssey:0,Legacy:0,Unknown:0,TS:"","Max jump range":""});let y=0,p=Date.now();const a=new e(socketUrl),v=new t(icon,idleTimeout),g=new n(document.body,infotemplate.content.children[0].cloneNode(!0));a.onopen=v.idle,a.onclose=v.off,a.onmessage=e=>{let t={};try{t=JSON.parse(e.data)}catch(e){return console.log("JSON parse error:",e),void v.error()}if(e=t.message){v.ok(),p=Date.now(),f.inc("Total");var o=function(e){try{var t,o=e.header.gameversion;return o&&(o.startsWith("CAPI-Legacy-")||parseInt(o)<4)?"Legacy":(t=e.message).odyssey?"Odyssey":t.horizons?"Horizons":!1===t.horizons?"Base":"Unknown"}catch(e){return console.log("gameversion error:",e),"Unknown"}}(t),n=(f.inc(o),document.createElement("tr"));n.classList.add("data"),n.classList.add(o),g.set(n,t),e.Taxi&&(f.inc("Taxi"),n.classList.add("taxi")),f.set("TS",e.timestamp);try{36e5<(a=new Date-new Date(e.timestamp))?(n.classList.add("old"),f.inc("Old")):a<-18e4&&(n.classList.add("new"),f.inc("New"))}catch(e){console.log("Invalid date:",e)}if(e.event)if(f.inc(e.event),"Scan"===e.event){if(n.append(m(e.BodyName),m(e.ScanType)),u(scanbods,n),!1===e.WasDiscovered&&"NavBeaconDetail"!==e.ScanType)if(e.StarType){const n=document.createElement("tr");n.classList.add("data"),n.classList.add(o),g.set(n,t),n.append(m(e.BodyName),m(e.StarType+" "+e.Subclass)),u(newstars,n)}else if(e.PlanetClass){const n=document.createElement("tr");n.classList.add("data"),n.classList.add(o),g.set(n,t),n.append(m(e.BodyName),m(e.PlanetClass),m(e.AtmosphereType&&"None"!==e.AtmosphereType?e.AtmosphereType:""),m(e.Landable?"Yes":"")),u(newplanets,n)}}else if("FSDJump"===e.event){if(n.append(m(e.StarSystem)),u(jumps,n),0{let t;"TR"===e.target.tagName?t=e.target:"TD"===e.target.tagName&&(t=e.target.parentNode),t&&g.has(t)&&g.show(t)}),function e(){a.readyState===WebSocket.OPEN&&Date.now()-p>resetTimeout&&(console.log("Receive timeout. Resetting connection."),a.refresh());var t=~~(6e4+42e3*Math.random());setTimeout(e,t)}(); +import{ReconnectingWebSocket as e}from"./reconnecting-websocket.min.js";import{ActivityIcon as t}from"./activity_icon.min.js";import{StatsBox as o}from"./statsbox.min.js";import{InfoBox as a}from"./infobox.min.js";import{distance3 as m,trimPrefix as d,makeTd as f,addRow as u,whatGame as p}from"./utils.min.js";const w=new o(statstable.querySelector("tbody"),{Total:0,Old:0,New:0,Ignored:0,Taxi:0,Base:0,Horizons:0,Odyssey:0,Legacy:0,Unknown:0,TS:"","Max jump range":""});let y=0,v=Date.now();const n=new e(socketUrl),x=new t(icon,idleTimeout),S=new a(document.body,infotemplate.content.children[0].cloneNode(!0));n.onopen=x.idle,n.onclose=x.off,n.onmessage=e=>{let t={};try{t=JSON.parse(e.data)}catch(e){return console.log("JSON parse error:",e),void x.error()}e=t.message;if(e){x.ok(),v=Date.now(),w.inc("Total");var o=p(t),a=(w.inc(o),document.createElement("tr"));a.classList.add("data"),a.classList.add(o),S.set(a,t),e.Taxi&&(w.inc("Taxi"),a.classList.add("taxi")),w.set("TS",e.timestamp);try{var n=new Date-new Date(e.timestamp);36e5{let t;"TR"===e.target.tagName?t=e.target:"TD"===e.target.tagName&&(t=e.target.parentNode),t&&S.has(t)&&S.show(t)}),function e(){n.readyState===WebSocket.OPEN&&Date.now()-v>resetTimeout&&(console.log("Receive timeout. Resetting connection."),n.refresh());var t=~~(6e4+42e3*Math.random());setTimeout(e,t)}(); diff --git a/html/js/statsbox.js b/html/js/statsbox.js index dab2cb8..c158624 100644 --- a/html/js/statsbox.js +++ b/html/js/statsbox.js @@ -1,3 +1,5 @@ +import { makeTd } from "./utils.min.js"; + class StatsBox { #statsbody; #stats; @@ -37,13 +39,10 @@ class StatsBox { this.#rows[stat].textContent = this.#stats[stat]; } else { const row = document.createElement("tr"); - row.append(StatsBox.#makeTd(stat), this.#rows[stat] = StatsBox.#makeTd(this.#stats[stat])); + row.append(makeTd(stat), this.#rows[stat] = makeTd(this.#stats[stat])); this.#statsbody.append(row); } } - - // TODO: move to inevitable utility module - static #makeTd = (textContent) => { const td = document.createElement("td"); td.textContent = textContent; return td; }; } export { StatsBox }; diff --git a/html/js/statsbox.min.js b/html/js/statsbox.min.js index d7690f0..1274aa1 100644 --- a/html/js/statsbox.min.js +++ b/html/js/statsbox.min.js @@ -1 +1 @@ -class i{#t;#i;#h;constructor(t,s={}){t.innerHTML="",this.#t=t,this.#i={},this.#h={};for(const i in s)this.set(i,s[i])}has(t){return t in this.#i}set(t,s){this.#i[t]=s,this.#o(t)}inc(t){this.has(t)||this.set(t,0),this.#i[t]++,this.#o(t)}#o(t){var s;t in this.#h?this.#h[t].textContent=this.#i[t]:((s=document.createElement("tr")).append(i.#u(t),this.#h[t]=i.#u(this.#i[t])),this.#t.append(s))}static#u=t=>{var s=document.createElement("td");return s.textContent=t,s}}export{i as StatsBox}; +import{makeTd as i}from"./utils.min.js";class t{#t;#i;#h;constructor(t,s={}){t.innerHTML="",this.#t=t,this.#i={},this.#h={};for(const i in s)this.set(i,s[i])}has(t){return t in this.#i}set(t,s){this.#i[t]=s,this.#o(t)}inc(t){this.has(t)||this.set(t,0),this.#i[t]++,this.#o(t)}#o(t){var s;t in this.#h?this.#h[t].textContent=this.#i[t]:((s=document.createElement("tr")).append(i(t),this.#h[t]=i(this.#i[t])),this.#t.append(s))}}export{t as StatsBox}; diff --git a/html/js/utils.js b/html/js/utils.js new file mode 100644 index 0000000..fdcfc1c --- /dev/null +++ b/html/js/utils.js @@ -0,0 +1,30 @@ +// const distanceN = (v0, v1) => Math.hypot.apply(null, v0.map((v, i) => v - v1[i])); +export const distance3 = (v0, v1) => Math.hypot(v0[0] - v1[0], v0[1] - v1[1], v0[2] - v1[2]); // subtract vectors, return length +export const trimPrefix = (str, prefix) => (str.startsWith(prefix) ? str.slice(prefix.length) : str).trim(); +export const makeTd = (textContent) => { const td = document.createElement("td"); td.textContent = td.title = textContent; return td; }; + +export function addRow(tbody, tr) { + while (tbody.childElementCount >= listLength) { + tbody.lastElementChild.remove(); + } + + tbody.prepend(tr); +} + +export function whatGame(data) { + try { + // no decision if gameversion is not set or set to CAPI- + // https://github.com/EDCD/EDDN/blob/live/docs/Developers.md#gameversions-and-gamebuild + const gameversion = data.header.gameversion; + if (gameversion && (gameversion.startsWith("CAPI-Legacy-") || parseInt(gameversion) < 4)) { + return "Legacy"; + } + + // https://github.com/EDCD/EDDN/blob/live/docs/Developers.md#horizons-and-odyssey-flags + const msg = data.message; + return msg.odyssey ? "Odyssey" : msg.horizons ? "Horizons" : msg.horizons === false ? "Base" : "Unknown"; + } catch(error) { + console.log("gameversion error:", error); + return "Unknown"; + } +} diff --git a/html/js/utils.min.js b/html/js/utils.min.js new file mode 100644 index 0000000..d5abcab --- /dev/null +++ b/html/js/utils.min.js @@ -0,0 +1 @@ +var n=(n,r)=>Math.hypot(n[0]-r[0],n[1]-r[1],n[2]-r[2]),r=(n,r)=>(n.startsWith(r)?n.slice(r.length):n).trim(),e=n=>{var r=document.createElement("td");return r.textContent=r.title=n,r};function t(n,r){for(;n.childElementCount>=listLength;)n.lastElementChild.remove();n.prepend(r)}function o(n){try{var r,e=n.header.gameversion;return e&&(e.startsWith("CAPI-Legacy-")||parseInt(e)<4)?"Legacy":(r=n.message).odyssey?"Odyssey":r.horizons?"Horizons":!1===r.horizons?"Base":"Unknown"}catch(n){return console.log("gameversion error:",n),"Unknown"}}export{n as distance3,r as trimPrefix,e as makeTd,t as addRow,o as whatGame};