diff --git a/Pulsar/Features/Journal/JournalService.cs b/Pulsar/Features/Journal/JournalService.cs index b959445..9e8ad76 100644 --- a/Pulsar/Features/Journal/JournalService.cs +++ b/Pulsar/Features/Journal/JournalService.cs @@ -10,7 +10,8 @@ public class JournalService( ILogger logger, IOptions options, IEventHubContext hub, - PulsarContext context + PulsarContext context, + IServiceProvider serviceProvider ) : IJournalService { public string FileName => FileHandlerService.JournalLogFileName; @@ -32,7 +33,7 @@ public class JournalService( new JsonSerializerOptions { PropertyNameCaseInsensitive = true, - Converters = { new JournalConverter(logger) } + Converters = { ActivatorUtilities.CreateInstance(serviceProvider) } })); foreach (var journal in select) diff --git a/Pulsar/Utils/HttpClient.cs b/Pulsar/Utils/HttpClient.cs deleted file mode 100644 index fb75fb5..0000000 --- a/Pulsar/Utils/HttpClient.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace Pulsar.Utils; - -public sealed class HttpClient -{ - private HttpClient() - { } - - private static readonly Lazy lazy = new Lazy(() => new System.Net.Http.HttpClient()); - - public static System.Net.Http.HttpClient Client => lazy.Value; - - public static string GetString(string url) - { - return lazy.Value.GetStringAsync(url).Result; - } - - public static HttpResponseMessage SendRequest(HttpRequestMessage request) - { - return lazy.Value.SendAsync(request).Result; - } - - public static Task SendRequestAsync(HttpRequestMessage request) - { - return lazy.Value.SendAsync(request); - } -} \ No newline at end of file diff --git a/Pulsar/Utils/JournalJsonConverter.cs b/Pulsar/Utils/JournalJsonConverter.cs index 2465399..98e00f5 100644 --- a/Pulsar/Utils/JournalJsonConverter.cs +++ b/Pulsar/Utils/JournalJsonConverter.cs @@ -288,6 +288,59 @@ public class JournalConverter(ILogger logger) : JsonConverter return JsonSerializer.Deserialize(ref reader)!; case "storedships": return JsonSerializer.Deserialize(ref reader)!; + case "scanorganic": + return JsonSerializer.Deserialize(ref reader)!; + case "market": + return JsonSerializer.Deserialize(ref reader)!; + case "missioncompleted": + return JsonSerializer.Deserialize(ref reader)!; + case "sellshiponrebuy": + return JsonSerializer.Deserialize(ref reader)!; + case "missionaccepted": + return JsonSerializer.Deserialize(ref reader)!; + case "approachsettlement": + return JsonSerializer.Deserialize(ref reader)!; + case "screenshot": + return JsonSerializer.Deserialize(ref reader)!; + case "moduleswap": + return JsonSerializer.Deserialize(ref reader)!; + case "underattack": + return JsonSerializer.Deserialize(ref reader)!; + case "datascanned": + return JsonSerializer.Deserialize(ref reader)!; + case "dockingdenied": + return JsonSerializer.Deserialize(ref reader)!; + case "fetchremotemodule": + return JsonSerializer.Deserialize(ref reader)!; + case "engineercontribution": + return JsonSerializer.Deserialize(ref reader)!; + case "collectcargo": + return JsonSerializer.Deserialize(ref reader)!; + case "moduleretrieve": + return JsonSerializer.Deserialize(ref reader)!; + case "marketbuy": + return JsonSerializer.Deserialize(ref reader)!; + case "selldrones": + return JsonSerializer.Deserialize(ref reader)!; + case "interdicted": + return JsonSerializer.Deserialize(ref reader)!; + case "sellorganicdata": + return JsonSerializer.Deserialize(ref reader)!; + case "wingadd": + return JsonSerializer.Deserialize(ref reader)!; + case "winginvite": + return JsonSerializer.Deserialize(ref reader)!; + case "wingjoin": + return JsonSerializer.Deserialize(ref reader)!; + case "wingleave": + return JsonSerializer.Deserialize(ref reader)!; + case "bounty": + return JsonSerializer.Deserialize(ref reader)!; + case "commitcrime": + return JsonSerializer.Deserialize(ref reader)!; + case "modulestore": + return JsonSerializer.Deserialize(ref reader)!; + default: logger.LogWarning("Unknown Journal event type {EventName}", eventName); return JsonSerializer.Deserialize(ref reader)!; diff --git a/Pulsar/WebApp/.vscode/launch.json b/Pulsar/WebApp/.vscode/launch.json new file mode 100644 index 0000000..28f6f3c --- /dev/null +++ b/Pulsar/WebApp/.vscode/launch.json @@ -0,0 +1,21 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "npm dev", + "runtimeExecutable": "npm", + "runtimeArgs": [ + "run-script", + "dev" + ], + "skipFiles": [ + "/**" + ] + } + ] +} \ No newline at end of file diff --git a/Pulsar/WebApp/src/lib/JournalLog.svelte b/Pulsar/WebApp/src/lib/JournalLog.svelte index 26e924c..52562d9 100644 --- a/Pulsar/WebApp/src/lib/JournalLog.svelte +++ b/Pulsar/WebApp/src/lib/JournalLog.svelte @@ -18,14 +18,14 @@
-

Journals

+

Live Journals

    {#each values as value (value.timestamp + value.event)} diff --git a/Pulsar/WebApp/src/lib/Status.svelte b/Pulsar/WebApp/src/lib/Status.svelte index 0c55fae..40d84f5 100644 --- a/Pulsar/WebApp/src/lib/Status.svelte +++ b/Pulsar/WebApp/src/lib/Status.svelte @@ -2,18 +2,65 @@ import { onMount } from "svelte"; import { statusStore } from "./stores/Status.store"; import connection from "./stores/Connection.store"; + import { StatusFlags, StatusFlags2 } from "../types/api/enums"; + import type JournalBase from "../types/api/JournalBase"; + import { slide } from "svelte/transition"; const x: string | null = $state(null); + const last: number[] = $state([]); + let timeToMax = $state(0); + + let loading = $state(true); + + let alert: JournalBase[] = $state([]); + onMount(async () => { await $connection.start(); + loading = false; + $connection.on("StatusUpdated", (message) => { statusStore.update((s) => { return { ...s, ...message }; }); + + // only 3 in array + if (last.length >= 3) { + last.shift(); + } + last.push(message.fuel?.fuelMain ?? 0); + + const change = []; + for (let i = last.length - 1; i === 0; i--) { + change.push(last[i] - last[i - 1]); + } + + const avg = change.reduce((a, b) => a + b, 0) / change.length; + const max = 32; + if ($statusStore.fuel?.fuelMain) { + timeToMax = (max - $statusStore.fuel?.fuelMain) / avg; + } + console.log($statusStore); }); + + $connection.on("JournalUpdated", (message) => { + const journals = message as JournalBase[]; + const targetEvents = ["HullDamage", "UnderAttack"]; + const events = journals.filter((j) => + targetEvents.find((t) => t.toLowerCase() === j.event.toLowerCase()) + ); + if (events.length) { + alert = events; + } + }); + + if (!$statusStore.pips) { + statusStore.set( + await (await fetch("http://localhost:5000/api/status")).json() + ); + } }); @@ -21,14 +68,48 @@
    +{#if loading} +

    LOADING ....

    +{/if} + +{#if alert.length} +

    Alert!

    + + {#each alert as a} + + {/each} + +{/if} +
    {#if $statusStore} - Fuel%: {(($statusStore.fuel?.fuelMain ?? 0) / 32) * 100}% Sys: {$statusStore?.pips?.sys ?? "?"} Eng: {$statusStore?.pips?.eng ?? - "?"} Wep: - {$statusStore?.pips?.wep ?? "?"}Fuel%: {(($statusStore.fuel?.fuelMain ?? 0) / 32) * 100}% est: {timeToMax}s +
    +
    + {#each [...Array($statusStore?.pips?.sys ?? 0)] as sys} +
    + {/each} +
    {$statusStore?.pips?.sys ?? "?"}
    +
    Sys
    +
    +
    + {#each [...Array($statusStore?.pips?.eng ?? 0)] as eng} +
    + {/each} +
    {$statusStore?.pips?.eng ?? "?"}
    +
    Eng
    +
    +
    + {#each [...Array($statusStore?.pips?.wep ?? 0)] as wep} +
    + {/each} +
    {$statusStore?.pips?.wep ?? "?"}
    +
    Wep
    +
    +
    + dest?: {$statusStore?.destination?.name} gui focus: {$statusStore.guiFocus} cargo: {$statusStore.cargo} @@ -39,9 +120,34 @@ {/if}
    - diff --git a/Pulsar/WebApp/src/routes/+page.svelte b/Pulsar/WebApp/src/routes/+page.svelte index a2ce11c..a34e7c0 100644 --- a/Pulsar/WebApp/src/routes/+page.svelte +++ b/Pulsar/WebApp/src/routes/+page.svelte @@ -33,5 +33,6 @@ div { flex: 50%; max-width: 100%; + height: 100%; } diff --git a/Pulsar/WebApp/src/routes/explorer/Explorer.svelte b/Pulsar/WebApp/src/routes/explorer/Explorer.svelte index a4bef6d..c4e067a 100644 --- a/Pulsar/WebApp/src/routes/explorer/Explorer.svelte +++ b/Pulsar/WebApp/src/routes/explorer/Explorer.svelte @@ -1,11 +1,34 @@

    Explorer

    + +

    Bodies

    + Scan: {scanned}/{totalBodies} +
    High Value (>500kcr)
    +
      + {#each bodies.filter((b) => b.value > 500000) as body} +
    1. [HMC/WW/ELT/ELN] $body.name - {body.value}cr
    2. + {/each} +
    +
    +
    +
    {#each data as row}
    diff --git a/Pulsar/WebApp/src/types/api/JournalBase.ts b/Pulsar/WebApp/src/types/api/JournalBase.ts new file mode 100644 index 0000000..81074dd --- /dev/null +++ b/Pulsar/WebApp/src/types/api/JournalBase.ts @@ -0,0 +1,4 @@ +export default interface JournalBase { + event: string; + timestamp: Date; +} diff --git a/Pulsar/WebApp/src/types/api/Status.ts b/Pulsar/WebApp/src/types/api/Status.ts index 489d72e..fe4059e 100644 --- a/Pulsar/WebApp/src/types/api/Status.ts +++ b/Pulsar/WebApp/src/types/api/Status.ts @@ -1,16 +1,22 @@ import type Destination from "./Destination"; import type Fuel from "./Fuel"; import type JournalBase from "./JournalBase"; +import type { + FocusStatus, + LegalStatus, + StatusFlags, + StatusFlags2, +} from "./enums"; export default interface Status extends JournalBase { event: "Status"; - flags: number; - flags2: number; + flags: StatusFlags; + flags2: StatusFlags2; pips: { eng: number; sys: number; wep: number }; - guiFocus: number; + guiFocus: FocusStatus; fuel: Fuel; cargo: number; - legalState: string; + legalState: LegalStatus; balance: number; destination: Destination; FireGroup: number; diff --git a/Pulsar/WebApp/src/types/api/enums.ts b/Pulsar/WebApp/src/types/api/enums.ts new file mode 100644 index 0000000..8439e8b --- /dev/null +++ b/Pulsar/WebApp/src/types/api/enums.ts @@ -0,0 +1,82 @@ +export enum StatusFlags { + Docked = 1, + Landed = 1 << 1, + LandingGear = 1 << 2, + Shields = 1 << 3, + Supercruise = 1 << 4, + FAOff = 1 << 5, + Hardpoints = 1 << 6, + Wing = 1 << 7, + Lights = 1 << 8, + CargoScoop = 1 << 9, + SilentRunning = 1 << 10, + FuelScooping = 1 << 11, + SRVBrake = 1 << 12, + SRVTurret = 1 << 13, + SRVProximity = 1 << 14, + SRVDriveAssist = 1 << 15, + Masslock = 1 << 16, + FSDCharging = 1 << 17, + FSDCooldown = 1 << 18, + LowFuel = 1 << 19, + Overheat = 1 << 20, + LatLongValid = 1 << 21, + InDanger = 1 << 22, + Interdiction = 1 << 23, + MainShip = 1 << 24, + Fighter = 1 << 25, + SRV = 1 << 26, + AnalysisHUD = 1 << 27, + NightVision = 1 << 28, + RadialAltitude = 1 << 29, + FSDJump = 1 << 30, + SRVHighBeam = 1 << 31, +} + +export enum StatusFlags2 { + OnFoot = 1, + InTaxi = 1 << 1, + InMulticrew = 1 << 2, + OnFootInStation = 1 << 3, + OnFootOnPlanet = 1 << 4, + AimDownSight = 1 << 5, + LowOxygen = 1 << 6, + LowHealth = 1 << 7, + Cold = 1 << 8, + Hot = 1 << 9, + VeryCold = 1 << 10, + VeryHot = 1 << 11, + GlideMode = 1 << 12, + OnFootInHangar = 1 << 13, + OnFootInSocialSpace = 1 << 14, + OnFootExterior = 1 << 15, + BreathableAtmosphere = 1 << 16, + TelepresenceMulticrew = 1 << 17, + PhysicalMulticrew = 1 << 18, + FsdHyperdriveCharging = 1 << 19, +} + +export type LegalStatus = + | "Clean" + | "IllegalCargo" + | "Speeding" + | "Wanted" + | "Hostile" + | "PassengerWanted" + | "Warrant" + | "Thargoid"; + +export enum FocusStatus { + NoFocus = 0, + InternalPanel = 1, + ExternalPanel = 2, + CommsPanel = 3, + RolePanel = 4, + StationServices = 5, + GalaxyMap = 6, + SystemMap = 7, + Orrery = 8, + FSS = 9, + SAA = 10, + Codex = 11, +}