From 75f180526d4e9ef2e7b075c51c067a1c3ae11211 Mon Sep 17 00:00:00 2001 From: punkfairie Date: Fri, 12 May 2023 03:00:15 -0700 Subject: [PATCH] System values estimated. --- index.html | 113 +++++---- package-lock.json | 19 +- package.json | 1 - src/@types/edsmResponses.d.ts | 16 ++ src/interfaces/EDSMInterface.js | 18 ++ src/interfaces/JournalInterface.ts | 359 +++++++++++++++++++++++++++++ src/models/Body.ts | 9 +- src/models/EDSM.ts | 34 ++- src/models/Journal.ts | 2 +- src/models/System.ts | 48 +++- src/models/UI.js | 39 +++- src/renderer.js | 14 +- tsconfig.json | 1 + 13 files changed, 572 insertions(+), 101 deletions(-) create mode 100644 src/@types/edsmResponses.d.ts create mode 100644 src/interfaces/EDSMInterface.js create mode 100644 src/interfaces/JournalInterface.ts diff --git a/index.html b/index.html index 01b55dc..68c081d 100644 --- a/index.html +++ b/index.html @@ -7,78 +7,69 @@ -
-
- -
-
-

-
Current Location
-

-
-
+ +
+
+

+
Current Location
+

+
+
- -
-
-
Name
-
Type
-
Distance
-
Details
-
Mapped Value
-
-
+ +
+
+
Name
+
Type
+
Distance
+
Details
+
Mapped Value
+
+
- -
-
-
- - Unknown -
-
-
+ +
- -
+
-
+ +
- -
+
-
+ +
- -
-
-

-
Nav Route
-

-
-
+
- -
-
-
LY
-
Name
-
Type
-
Mapped Value
-
-
+ +
+
+

+
Nav Route
+

+
+
- - + + + + +
+
+

diff --git a/package-lock.json b/package-lock.json index 2b329ec..6f445d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,6 @@ "dependencies": { "bootstrap": "^5.3.0-alpha3", "chokidar": "^3.5.3", - "electron-fetch": "^1.9.1", "electron-squirrel-startup": "^1.0.0", "glob": "^10.2.2", "lodash-es": "^4.17.21", @@ -2292,17 +2291,6 @@ "node": ">= 12.20.55" } }, - "node_modules/electron-fetch": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/electron-fetch/-/electron-fetch-1.9.1.tgz", - "integrity": "sha512-M9qw6oUILGVrcENMSRRefE1MbHPIz0h79EKIeJWK9v563aT9Qkh8aEHPO1H5vi970wPirNY+jO9OpFoLiMsMGA==", - "dependencies": { - "encoding": "^0.1.13" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/electron-installer-common": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/electron-installer-common/-/electron-installer-common-0.10.3.tgz", @@ -2823,6 +2811,8 @@ "version": "0.1.13", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "optional": true, "dependencies": { "iconv-lite": "^0.6.2" } @@ -2831,6 +2821,8 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "optional": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -5834,7 +5826,8 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "node_modules/sass": { "version": "1.62.1", diff --git a/package.json b/package.json index 8c109db..1f93862 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,6 @@ "dependencies": { "bootstrap": "^5.3.0-alpha3", "chokidar": "^3.5.3", - "electron-fetch": "^1.9.1", "electron-squirrel-startup": "^1.0.0", "glob": "^10.2.2", "lodash-es": "^4.17.21", diff --git a/src/@types/edsmResponses.d.ts b/src/@types/edsmResponses.d.ts new file mode 100644 index 0000000..96df08f --- /dev/null +++ b/src/@types/edsmResponses.d.ts @@ -0,0 +1,16 @@ +interface valuableBody { + bodyId: number, + bodyName: string, + distance: number, + valueMax: number, +} + +export interface systemEstimatedValue { + id: number, + id64: number, + name: string, + url: string, + estimatedValue: number, + estimatedValueMapped: number, + valuableBodies: valuableBody[] +} \ No newline at end of file diff --git a/src/interfaces/EDSMInterface.js b/src/interfaces/EDSMInterface.js new file mode 100644 index 0000000..182c2b0 --- /dev/null +++ b/src/interfaces/EDSMInterface.js @@ -0,0 +1,18 @@ +class EDSM { + constructor() { + this.data = {} + this.dataError = false + } + + request(url) { + return fetch(url) + .then(response => { + if (!response.ok) { + throw new Error('HTTP error' + response.status) + } + return response.json() + }) + .then(json => this.data = json) + .catch(() => this.dataError = true) + } +} \ No newline at end of file diff --git a/src/interfaces/JournalInterface.ts b/src/interfaces/JournalInterface.ts new file mode 100644 index 0000000..bed3654 --- /dev/null +++ b/src/interfaces/JournalInterface.ts @@ -0,0 +1,359 @@ +import type { Tail as TailType } from 'tail' +import type { autoScan, completeFsdJump, detailedScan, journalEntry, navRoute, planetScan } from '../@types/journalLines' + +const chokidar = require('chokidar') +const EventEmitter = require('node:events') +const fs = require('node:fs') +const { globSync } = require('glob') +import * as _ from 'lodash-es' +const os = require('node:os') +const path = require('node:path') +const { readFile } = require('node:fs/promises') +const reverseLineReader = require('reverse-line-reader') +const Tail = require('tail').Tail + +import { Body } from '../models/Body' +import { System } from '../models/System' + +// Set log() to console.log() so whenever I get around to setting up a log file, I don't have to +// search and replace all the console.log()'s. +const log = console.log.bind(console) + +export class JournalInterface extends EventEmitter { + journalDir: null|string + journalPattern: string + currentJournal: string|undefined + location: System + navRoute: System[] + + + constructor(isPackaged: boolean) { + super() + + this.journalDir = null + if (!isPackaged) { // Account for WSL during development + this.journalDir = "/mnt/c/Users/marle/Saved\ Games/Frontier\ Developments/Elite\ Dangerous/" + } else if (os.platform() === 'win32') { // Windows + this.journalDir = os.homedir() + '\\Saved Games\\Frontier Developments\\Elite Dangerous' + } else if (os.platform() === 'linux') { // Linux + this.journalDir = os.homedir() + '/.local/share/Steam/steamapps/compatdata/359320/pfx/drive_c/users/steamuser/Saved Games/Frontier Developments/Elite Dangerous/' + } else { + log(`ERROR: Journal files not found. OS: ${os.platform()}.`) + } + + this.journalPattern = this.journalDir + "Journal.*.log" + + this.currentJournal = this.getLatestJournal() + log(`New journal file found, now watching ${path.basename(this.currentJournal)}.`) + + this.navRoute = [] + + // LineReader seems to be async, so start async processes here. + this.location = new System('Unknown') + + log('JournalInterface initialized. Attempting to find current location.') + this.getCurrentLocation() + // -> getScannedBodies() + // --> getNavRoute() + } + + /* -------------------------------------------------------------------- getLatestJournal ---- */ + + // https://stackoverflow.com/questions/15696218/get-the-most-recent-file-in-a-directory-node-js + getLatestJournal(): string|undefined { + const journals = globSync(this.journalPattern) + + return _.maxBy(journals, file => fs.statSync(file).mtime) + } + + /* ------------------------------------------------------------------ getCurrentLocation ---- */ + + // Get current location on setup, so if app is restarted, user can pick up where they left off + // Rather than waiting til they jump to the next system to use the program again. + getCurrentLocation(): void { + reverseLineReader.eachLine(this.currentJournal, (raw: string, last: boolean) => { + if (raw) { // skip blank line at end of file + const line = JSON.parse(raw) + + if (line.event === 'FSDJump') { + this.location = new System(line) + log(`Current location set to ${this.location.name}.`) + this.emit('ENTERED_NEW_SYSTEM') + return false + } else if (last) { + log('Unable to find last hyperspace jump. Searching for last known location.') + return false + } + } + }).then(() => { + reverseLineReader.eachLine(this.currentJournal, (raw: string, last: boolean) => { + // TODO: figure out if we can avoid entering eachLine() altogether? realyyy wish + // it returned a promise :( + if (this.location.name !== 'Unknown') { + return false + } + + if (raw) { + const line = JSON.parse(raw) + + if (line.event === 'Location') { + this.location = new System(line) + log(`Current location set to ${this.location.name}.`) + this.emit('ENTERED_NEW_SYSTEM') + return false + } else if (last) { + log('WARNING: Unable to find last known location.') + return false + } + } + }).then(() => { + if (this.location.name !== 'Unknown') { + log('Attempting to find scanned bodies in current system.') + this.getScannedBodies() + } + }) + }) + } + + /* -------------------------------------------------------------------- getScannedBodies ---- */ + + // Look for all scanned bodies before last FSDJump, for same reasons as getCurrentLocation(). + getScannedBodies(): void { + let detailedScanLine: detailedScan|null = null + + reverseLineReader.eachLine(this.currentJournal, (raw: string, last: boolean) => { + + if (raw) { // Skip blank line at end of file. + const line: journalEntry = JSON.parse(raw) + + // Check if previous line was ScanType = Detailed, and handle that. + if (detailedScanLine !== null) { + if (line.event === 'SAAScanComplete') { + // This was a DSS, so add to list with DSS flag set to true. + this.location.bodies.push(new Body(detailedScanLine, true)) + } else { + // Else, check that the body hasn't already been added (by a DSS scan line). + let dupChecker = {'BodyName': detailedScanLine.BodyName, 'BodyID': detailedScanLine.BodyID} + let r = _.find(this.location.bodies, dupChecker) + + if (r === undefined) { + // Body was not already logged, so add to list. + this.location.bodies.push(new Body(detailedScanLine)) + } + } + + // Finally, clear the variable. + detailedScanLine = null + } + + // Now move on to evaluating the current line. + if (line.event === 'Scan' && 'ScanType' in line) { + // If ScanType = Detailed and body is not a star, save the line so we can check + // the one immediately above for event = SAAScanComplete, which indicates this + // was a DSS. + if (line.ScanType === 'Detailed' && !('StarType' in line)) { + detailedScanLine = (line as detailedScan) + + } else if ('StarType' in line) { // Save stars to bodies list. + this.location.bodies.push(new Body((line as autoScan|detailedScan))) + + } else if (line.ScanType === 'AutoScan') { // Save auto/discovery scan bodies. + // Check if planet, and then do the duplicate check (otherwise it's an + // astroid, as we've already accounted for stars). + if ('PlanetClass' in line) { + let dupChecker = {'BodyName': (line as planetScan<'AutoScan'>).BodyName, 'BodyID': (line as planetScan<'AutoScan'>).BodyID} + let r = _.find(this.location.bodies, dupChecker) + + if (r === undefined) { + this.location.bodies.push(new Body((line as autoScan))) + } + + } else { // Asteroids. + this.location.bodies.push(new Body((line as autoScan))) + } + } + } else if (line.event === 'FSDJump') { + // Stop evaluating once we reach the beginning of current system entries. + return false + } + } + }).then(() => { + log('Scanned bodies found.') + log('Reading current nav route.') + this.getNavRoute(true) + }) + } + + /* ---------------------------------------------------------------------- watchDirectory ---- */ + + // Set up journal directory watcher to catch new journal files as the game seems to sometimes + // make more than one journal per day. + // Also for instances where UTC day switches over mid-play session. + watchDirectory(): void { + const watcher = chokidar.watch(this.journalPattern, {usePolling: true, persistent: true}) + + watcher.on('add', () => this.currentJournal = this.getLatestJournal()) + + log('Watching journal folder for changes...') + } + + /* ----------------------------------------------------------------------- parseScanLine ---- */ + + // Parse and handle scan lines. + parseScanLine(line: autoScan|detailedScan, DSS: boolean = false) { + const dupChecker = {'BodyName': line.BodyName, 'BodyID': line.BodyID} + let body: Body|null = null + + // If it's a DSS scan, then we should have already added the body to the list. But we'll + // check to make sure. + if (DSS) { + // Using findIndex() rather than find() so we can edit the body if found. + // @ts-ignore since it doesn't understand dupChecker is a valid predicate. + let bodyIndex: number = _.findIndex(this.location.bodies, dupChecker) + + if (bodyIndex > -1) { // Body was found in list, so simply toggle the DSS flag. + body = (this.location.bodies[bodyIndex] as Body) + body.DSSDone = true + } else { // Body was missed on initial journal scan, so add it to the list. + body = new Body(line, true) + this.location.bodies.push(body) + } + + } else { // Otherwise it's an FSS or auto scan, and needs to be added to the list. + // Probably overkill, but do a duplicate check just in case. + let r = _.find(this.location.bodies, dupChecker) + + if (r === undefined) { + body = new Body(line) + this.location.bodies.push(body) + } + } + + log(`Scan detected. Body: ${line.BodyName}.`) + this.emit('BODY_SCANNED', body, DSS) + } + + /* ------------------------------------------------------------------------- getNavRoute ---- */ + + async getNavRoute(init: boolean = false) { + this.navRoute = [] // clear previous route, to catch overwritten routes + let routeFile: string|null = null + + try { + routeFile = await readFile(this.journalDir + 'NavRoute.json', { encoding: 'utf8' }) + } catch (err) { + log(`Error reading nav route file: ${err.message}.`) + } + + if (routeFile) { + const route: navRoute = JSON.parse(routeFile) + + // system -> skip + // CURRENT -> push = true; skip + // system -> push + + let push: boolean = false + route.Route.forEach((system) => { + if (!push && system.SystemAddress === this.location.SystemAddress) { + push = true + } + + if (push && system.SystemAddress !== this.location.SystemAddress) { + this.navRoute.push(new System(system)) + } + }) + + if (this.navRoute.length > 0) { + log('Nav route set.') + } else { + log('No nav route found.') + } + + if (init) { + this.emit('INIT_COMPLETE') + } + + this.emit('SET_NAV_ROUTE') + } + } + + /* ----------------------------------------------------------------------- handleFsdJump ---- */ + + handleFsdJump(line: completeFsdJump): void { + this.location = new System((line as completeFsdJump)) + log(`FSD Jump detected, current location updated to ${this.location.name}.`) + + if (this.navRoute.length > 0) { + _.remove(this.navRoute, (system) => { + return system.SystemAddress === this.location.SystemAddress + }) + } + + this.emit('ENTERED_NEW_SYSTEM') + } + + /* --------------------------------------------------------------------------- parseLine ---- */ + + // Parse and handle journal lines. + parseLine(raw: string) { + const line: journalEntry = JSON.parse(raw) + let DSSFlag: boolean = false + + switch (line.event) { + // Hyperspace jump started (3.. 2.. 1..) + case 'StartJump': { + if ('JumpType' in line && line.JumpType === 'Hyperspace') { + this.emit('ENTERING_WITCH_SPACE') + } + break + } + + // CMDR jumped to new system, so update current location. + case 'FSDJump': { + this.handleFsdJump((line as completeFsdJump)) + break + } + + // CMDR completed DSS scan, so set flag for when next line processes and we want to + // figure out what kind of scan occurred. + case 'SAAScanComplete': { + DSSFlag = true + break + } + + // A scan occurred, so let's hand that info off to the appropriate function and then + // reset the DSS flag. + case 'Scan': { + this.parseScanLine((line as autoScan|detailedScan), DSSFlag) + DSSFlag = false + break + } + + // CMDR set a new nav route. + case 'NavRoute': { + this.getNavRoute() + break + } + + // CMDR cleared the nav route. + case 'NavRouteClear': { + this.navRoute = [] + log('Nav route cleared.') + this.emit('SET_NAV_ROUTE') + break + } + } + } + + /* ------------------------------------------------------------------------ watchJournal ---- */ + + // Watch the journal for changes. + watchJournal(): void { + const tail: TailType = new Tail(this.currentJournal, {useWatchFile: true}) + + log(`Watching ${path.basename(this.currentJournal)}...`) + + tail.on('line', data => data ? this.parseLine(data) : undefined) + tail.on('error', err => log(`Tail error in JournalInterface.watchJournal(): ${err}`)) + } +} \ No newline at end of file diff --git a/src/models/Body.ts b/src/models/Body.ts index 1fc5cdd..a68a0d6 100644 --- a/src/models/Body.ts +++ b/src/models/Body.ts @@ -1,10 +1,11 @@ +import type { valuableBody } from "../@types/edsmResponses" import type { asteroidScan, autoScan, detailedScan, planetScan, starScan } from "../@types/journalLines" export interface Body extends starScan<'AutoScan'|'DetailedScan'>, asteroidScan<'AutoScan'|'DetailedScan'>, planetScan<'AutoScan'|'DetailedScan'> {} export class Body { DSSDone: boolean - constructor(journalLine: autoScan|detailedScan|null = null, DSS: boolean = false) { + constructor(journalLine: autoScan|detailedScan|valuableBody|null = null, DSS: boolean = false) { this.DSSDone = DSS if (journalLine !== null) { @@ -79,10 +80,4 @@ export class Body { return typeIcon } - - /* ---------------------------------------------------------------------------- distance ---- */ - - distance(): string { - return Intl.NumberFormat().format(Math.round(this.DistanceFromArrivalLS)) - } } \ No newline at end of file diff --git a/src/models/EDSM.ts b/src/models/EDSM.ts index 5008e55..01207a2 100644 --- a/src/models/EDSM.ts +++ b/src/models/EDSM.ts @@ -1,10 +1,28 @@ -import fetch from 'electron-fetch' +import type { systemEstimatedValue } from '../@types/edsmResponses' + +const EventEmitter = require('node:events') import { Log } from './Log' +import { System } from './System' -class EDSM { - private constructor() {} +export class EDSM extends EventEmitter { + static #instance: EDSM - static async request(url: string, options: {[x: string]: string}): Promise { + private constructor() { + super() + } + + static connect(): EDSM { + if (!EDSM.#instance) { + EDSM.#instance = new EDSM() + } + + return EDSM.#instance + } + + /* ---------------------------------------------------------------------------- #request ---- */ + + // Submit a request to EDSM and return the response as an object + static async #request(url: string, options: {[x: string]: string}): Promise { let data: object|undefined = undefined try { @@ -21,4 +39,12 @@ class EDSM { return data } + + /* ---------------------------------------------------------------------- getSystemValue ---- */ + + static async getSystemValue(system: System): Promise { + const url = 'https://www.edsm.net/api-system-v1/estimated-value' + const response = await EDSM.#request(url, {systemName: system.name}) + return (response as systemEstimatedValue) + } } \ No newline at end of file diff --git a/src/models/Journal.ts b/src/models/Journal.ts index 4ba0401..ee92f18 100644 --- a/src/models/Journal.ts +++ b/src/models/Journal.ts @@ -22,7 +22,7 @@ export class Journal extends EventEmitter { super() this.#path = journalPath - this.location = new System('Unknown') + this.location = new System() this.navRoute = [] // Start ReverseLineReader chain here. diff --git a/src/models/System.ts b/src/models/System.ts index f807e0a..22ff09b 100644 --- a/src/models/System.ts +++ b/src/models/System.ts @@ -1,17 +1,24 @@ import type { completeFsdJump, location, navRouteSystem } from "../@types/journalLines" import { Body } from "./Body" +import { EDSM } from "./EDSM" export class System { name: string SystemAddress?: number StarClass?: string + charted: boolean bodies: Body[] - constructor(line: navRouteSystem|completeFsdJump|location|string) { + // ESDM data + estimatedValue?: number + estimatedValueMapped?: number + valuableBodies?: Body[] + + constructor(line?: navRouteSystem|completeFsdJump|location) { // In future, this is where we preform EDSM lookup - if (typeof line === 'string') { - this.name = line + if (!line) { + this.name = 'Unknown' } else { this.name = line.StarSystem this.SystemAddress = line.SystemAddress @@ -19,8 +26,43 @@ export class System { if ('StarClass' in line) { this.StarClass = line.StarClass } + } + // Set this to true initially, since it likely is and the system is technically inserted + // into the UI before it's appraised. + this.charted = true this.bodies = [] + + if (this.name !== 'Unknown') { + this.#getValue() + } + } + + /* --------------------------------------------------------------------------- #getValue ---- */ + + async #getValue() { + // display estimatedValueMapped + const data = await EDSM.getSystemValue(this) + + if (data) { + this.estimatedValue = data.estimatedValue + this.estimatedValueMapped = data.estimatedValueMapped + + // If EDSM doesn't have an estimate, then it's likely undiscovered. + this.charted = this.estimatedValue > 0 + + // Save valuable bodies in system, if any. + if (data.valuableBodies.length > 0) { + this.valuableBodies = [] + + data.valuableBodies.forEach((body) => { + this.valuableBodies?.push(new Body(body)) + }) + } + + // Let the UI know it needs to update. + EDSM.connect().emit('SYSTEM_APPRAISED', this) + } } } \ No newline at end of file diff --git a/src/models/UI.js b/src/models/UI.js index d0fc084..bdbf8e2 100644 --- a/src/models/UI.js +++ b/src/models/UI.js @@ -1,6 +1,12 @@ export class UI { constructor() {} + /* ----------------------------------------------------------------------- #formatNumber ---- */ + + static #formatNumber(number) { + return Intl.NumberFormat().format(Math.round(number)) + } + /* --------------------------------------------------------------------- enterWitchSpace ---- */ static enterWitchSpace() { @@ -18,16 +24,20 @@ export class UI { static setCurrentSystem(system) { $('#highValueScans').children().remove() $('#lowValueScans').children().remove() + $('#currentSystem').children().remove() + + let row if (system.name === 'Unknown') { - $('#currentSystem').removeClass('charted').addClass('highlighted text-center') - $('#currentSystemIcon').addClass('hidden') + row = $('
').addClass('row ms-1 me-1') + const child = $('
').addClass('col system highlighted text-center') + child.text(system.name) + row.appendChild(child) } else { - $('#currentSystem').addClass('charted').removeClass('highlighted text-center') - $('#currentSystemIcon').removeClass('hidden') + row = UI.createSystemRow(system) } - $('#currentSystemName').text(system.name) + $('#currentSystem').appendChild(row) } /* -------------------------------------------------------------------------- buildRings ---- */ @@ -103,7 +113,7 @@ export class UI { // distance const distance = $('
').addClass(`col-auto ps-2 ms-0 system ${chartedStyle}`) - distance.text(body.distance()) + distance.text(UI.#formatNumber(body.DistanceFromArrivalLS)) row.appendChild(distance) // info @@ -135,8 +145,8 @@ export class UI { static createSystemRow(system) { const row = $('
').addClass('row ms-1 me-1') row.attr('id', system.SystemAddress) - // TODO APPRAISAL DATA - const chartedStyle = 'charted' + // This is probably still the default 'true' value, but check in case the fetch() was quick. + const chartedStyle = system.charted ? 'charted' : 'uncharted' // name const name = $('
').addClass(`col system ${chartedStyle}`) @@ -145,10 +155,19 @@ export class UI { row.appendChild(name) // mapped value - // TODO APPRAISAL DATA - const value = $('
').addClass(`col-2 text-end system ${chartedStyle}`) + // Check if EDSM has responded yet, otherwise value will be filled in later. + const value = $('
').addClass(`col-2 text-end system ${chartedStyle} value`) + if ('estimatedValueMapped' in system) { + value.text(UI.#formatNumber(system.estimatedValueMapped)) + } row.appendChild(value) return row } + + /* ---------------------------------------------------------------------------- setValue ---- */ + + static setValue(row, value) { + row.children().filter('.value').text(UI.#formatNumber(value)) + } } \ No newline at end of file diff --git a/src/renderer.js b/src/renderer.js index 5503910..c25c167 100644 --- a/src/renderer.js +++ b/src/renderer.js @@ -35,6 +35,7 @@ import { Safari } from './models/Safari' import { UI } from './models/UI' import { Body } from './models/Body' import { sep } from 'path' +import { EDSM } from './models/EDSM' // Grab app.isPackaged from main process let isPackaged = false @@ -48,6 +49,7 @@ window.process.argv.forEach((item) => { const safari = Safari.start(isPackaged) const journal = safari.journal +const edsm = EDSM.connect() if (!journal) { // handle error @@ -77,7 +79,7 @@ journal.on('ENTERING_WITCH_SPACE', () => UI.enterWitchSpace()) journal.on('ENTERED_NEW_SYSTEM', () => { UI.setCurrentSystem(journal.location) - $(`#${CSS.escape(journal.location.SystemAddress)}`).remove() + $('#navRoute').children().filter(`#${CSS.escape(journal.location.SystemAddress)}`).remove() // verify that the internal navRoute matches the UI navRoute, and rebuild it if not if ($('#navRoute').children().length !== journal.navRoute.length) { @@ -126,4 +128,14 @@ journal.on('SET_NAV_ROUTE', () => { } }) } +}) + +/* ------------------------------------------------------------------------ system value set ---- */ + +edsm.on('SYSTEM_APPRAISED', (system) => { + const systemRow = $(`#${CSS.escape(system.SystemAddress)}`) + + if (systemRow.length > 0) { + UI.setValue(systemRow, system.estimatedValueMapped) + } }) \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 185bdf6..6261f3c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,6 +2,7 @@ "extends": "@tsconfig/node20/tsconfig.json", "compilerOptions": { "useUnknownInCatchVariables": false, + "lib": ["DOM"] }, "include": ["src"], "exclude": ["node_modules"]