diff --git a/src/app.css b/src/app.css index 6ff7062..d310a59 100644 --- a/src/app.css +++ b/src/app.css @@ -3,68 +3,49 @@ @tailwind utilities; @layer base { - :root { - --background: 0 0% 100%; - --foreground: 222.2 84% 4.9%; - - --muted: 210 40% 96.1%; - --muted-foreground: 215.4 16.3% 46.9%; - - --popover: 0 0% 100%; - --popover-foreground: 222.2 84% 4.9%; - - --card: 0 0% 100%; - --card-foreground: 222.2 84% 4.9%; - - --border: 214.3 31.8% 91.4%; - --input: 214.3 31.8% 91.4%; - - --primary: 222.2 47.4% 11.2%; - --primary-foreground: 210 40% 98%; - - --secondary: 210 40% 96.1%; - --secondary-foreground: 222.2 47.4% 11.2%; - - --accent: 210 40% 96.1%; - --accent-foreground: 222.2 47.4% 11.2%; - - --destructive: 0 72.2% 50.6%; - --destructive-foreground: 210 40% 98%; - - --ring: 222.2 84% 4.9%; - + :root { + --background: 239 19% 95%; + --foreground: 239 5% 0%; + --card: 239 19% 90%; + --card-foreground: 239 5% 10%; + --popover: 239 19% 95%; + --popover-foreground: 239 95% 0%; + --primary: 239 58% 35%; + --primary-foreground: 0 0% 100%; + --secondary: 239 19% 70%; + --secondary-foreground: 0 0% 0%; + --muted: 201 19% 85%; + --muted-foreground: 239 5% 35%; + --accent: 201 19% 80%; + --accent-foreground: 239 5% 10%; + --destructive: 0 50% 30%; + --destructive-foreground: 239 5% 90%; + --border: 239 20% 50%; + --input: 239 20% 18%; + --ring: 239 58% 35%; --radius: 0.5rem; } - - .dark { - --background: 222.2 84% 4.9%; - --foreground: 210 40% 98%; - - --muted: 217.2 32.6% 17.5%; - --muted-foreground: 215 20.2% 65.1%; - - --popover: 222.2 84% 4.9%; - --popover-foreground: 210 40% 98%; - - --card: 222.2 84% 4.9%; - --card-foreground: 210 40% 98%; - - --border: 217.2 32.6% 17.5%; - --input: 217.2 32.6% 17.5%; - - --primary: 210 40% 98%; - --primary-foreground: 222.2 47.4% 11.2%; - - --secondary: 217.2 32.6% 17.5%; - --secondary-foreground: 210 40% 98%; - - --accent: 217.2 32.6% 17.5%; - --accent-foreground: 210 40% 98%; - - --destructive: 0 62.8% 30.6%; - --destructive-foreground: 210 40% 98%; - - --ring: hsl(212.7,26.8%,83.9); + .dark { + --background: 239 19% 5%; + --foreground: 239 5% 90%; + --card: 239 19% 0%; + --card-foreground: 239 5% 90%; + --popover: 239 19% 5%; + --popover-foreground: 239 5% 90%; + --primary: 239 58% 35%; + --primary-foreground: 0 0% 100%; + --secondary: 239 19% 10%; + --secondary-foreground: 0 0% 100%; + --muted: 201 19% 15%; + --muted-foreground: 239 5% 60%; + --accent: 201 19% 15%; + --accent-foreground: 239 5% 90%; + --destructive: 0 50% 30%; + --destructive-foreground: 239 5% 90%; + --border: 239 20% 18%; + --input: 239 20% 18%; + --ring: 239 58% 35%; + --radius: 0.5rem; } } diff --git a/src/lib/components/InventoryList.svelte b/src/lib/components/InventoryList.svelte new file mode 100644 index 0000000..ccb0c88 --- /dev/null +++ b/src/lib/components/InventoryList.svelte @@ -0,0 +1,34 @@ + + + + +
+ {#if valid} + {#each inventories as inventory, index} +

+ - {i18n.localize(inventory.details.name)} {i18n.localize("volume")}: {applyUnits(i18n, inventory.getVolume(grid, multiplier), "l")} + +

+ {/each} + {:else} +

Invalid Props

+ {/if} +
\ No newline at end of file diff --git a/src/lib/components/NewInventory.svelte b/src/lib/components/NewInventory.svelte new file mode 100644 index 0000000..4533e7b --- /dev/null +++ b/src/lib/components/NewInventory.svelte @@ -0,0 +1,66 @@ + + + + +{#if valid} +
+ + + + + + updateDetails(change)}> + {#each Object.values(INVENTORIES) as inventory} + {i18n.localize(inventory.name)} + {/each} + + + + +
+{:else} +

Invalid Props

+{/if} \ No newline at end of file diff --git a/src/lib/components/NewThruster.svelte b/src/lib/components/NewThruster.svelte new file mode 100644 index 0000000..7848146 --- /dev/null +++ b/src/lib/components/NewThruster.svelte @@ -0,0 +1,115 @@ + + + + +
+ {#if valid} +
+
+ + + + + + + {#each sizes as thrusterSize} + {i18n.localize(thrusterSize)} + {/each} + + + +
+ + + + + + {updateDetails(change)}}> + {#each Object.values(THRUSTER_TYPE_LIST) as thrusterType} + {i18n.localize(thrusterType.name)} + {/each} + + + +
+ + {:else} +

Invalid Props

+ {/if} +
\ No newline at end of file diff --git a/src/lib/components/ThrusterList.svelte b/src/lib/components/ThrusterList.svelte new file mode 100644 index 0000000..5356fbc --- /dev/null +++ b/src/lib/components/ThrusterList.svelte @@ -0,0 +1,34 @@ + + + + + +
+ {#if valid} + {#each thrusters as thruster, index} +

+ - {i18n.localize(thruster.details.size)} {i18n.localize(thruster.details.type.details.name)}: {applyUnits(i18n, thruster.getThrust(grid, atmosphere), "N")} + +

+ {/each} + {:else} +

Invalid Props

+ {/if} +
\ No newline at end of file diff --git a/src/lib/components/object-values.ts b/src/lib/components/object-values.ts new file mode 100644 index 0000000..4fdd2c1 --- /dev/null +++ b/src/lib/components/object-values.ts @@ -0,0 +1 @@ +export type ObjectValues = T[keyof T]; \ No newline at end of file diff --git a/src/lib/constants.ts b/src/lib/constants.ts index c5898cf..c804e52 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -1,114 +1,3 @@ -export enum Grids { - Small = "smallGrid", - Large = "largeGrid" -} - -export enum ThrusterFuel { - Electric = "electric", - Hydrogen = "hydrogen", - Deuterium = "deuterium" -} - -export class ThrusterTypeDetails { - atmosphericFactor: number; - vacuumFactor: number; - fuel: ThrusterFuel; - sizes: Map; - - constructor(atmos: number, vacuum: number, fuel: ThrusterFuel, sizes: Map) { - this.atmosphericFactor = atmos; - this.vacuumFactor = vacuum; - this.fuel = fuel; - this.sizes = sizes; - } -} - -export enum ThrusterSize { - Small = "smallThruster", - Large = "largeThruster", - Huge = "hugeThruster", -} - -export enum ThrusterType { - Ion = "ion", - Atmospheric = "atmos", - Hydrogen = "hydrogen", - Fusion = "fusion" -} - -export class ThrusterSizeDetails { - thrust: number; - maxFuelConsumption: number; - - constructor(thrust: number, maxFuelConsumption = 0) { - this.thrust = thrust; - this.maxFuelConsumption = maxFuelConsumption; - } -} - -export const thrusterDetails: Map> = new Map([ - [Grids.Large, new Map([ - [ThrusterType.Atmospheric, new ThrusterTypeDetails(1, 0, ThrusterFuel.Electric, new Map([ - [ThrusterSize.Large, new ThrusterSizeDetails(4500000)], - [ThrusterSize.Small, new ThrusterSizeDetails(350000)] - ]))], - [ThrusterType.Ion, new ThrusterTypeDetails(0.2, 1, ThrusterFuel.Electric, new Map([ - [ThrusterSize.Large, new ThrusterSizeDetails(4320000)], - [ThrusterSize.Small, new ThrusterSizeDetails(345600)] - ]))], - [ThrusterType.Hydrogen, new ThrusterTypeDetails(1, 1, ThrusterFuel.Hydrogen, new Map([ - [ThrusterSize.Large, new ThrusterSizeDetails(7200000)], - [ThrusterSize.Small, new ThrusterSizeDetails(1080000)] - ]))], - [ThrusterType.Fusion, new ThrusterTypeDetails(0.5, 1, ThrusterFuel.Deuterium, new Map([ - [ThrusterSize.Large, new ThrusterSizeDetails(33780000)], - [ThrusterSize.Small, new ThrusterSizeDetails(9040000)] - ]))] - - ])], - [Grids.Small, new Map([ - [ThrusterType.Atmospheric, new ThrusterTypeDetails(1, 0, ThrusterFuel.Electric, new Map([ - [ThrusterSize.Large, new ThrusterSizeDetails(340000)], - [ThrusterSize.Small, new ThrusterSizeDetails(65000)] - ]))], - [ThrusterType.Ion, new ThrusterTypeDetails(0.2, 1, ThrusterFuel.Electric, new Map([ - [ThrusterSize.Large, new ThrusterSizeDetails(172800)], - [ThrusterSize.Small, new ThrusterSizeDetails(14400)] - ]))], - [ThrusterType.Hydrogen, new ThrusterTypeDetails(1, 1, ThrusterFuel.Hydrogen, new Map([ - [ThrusterSize.Large, new ThrusterSizeDetails(480000)], - [ThrusterSize.Small, new ThrusterSizeDetails(98400)] - ]))], - [ThrusterType.Fusion, new ThrusterTypeDetails(0.5, 1, ThrusterFuel.Deuterium, new Map([ - [ThrusterSize.Huge, new ThrusterSizeDetails(9040000)], - [ThrusterSize.Large, new ThrusterSizeDetails(1030000)], - [ThrusterSize.Small, new ThrusterSizeDetails(210000)] - ]))] - ])] -]) - -export enum InventoryType { - Connector = "connector", - CargoSmall = "smallCargo", - CargoMedium = "mediumCargo", - CargoLarge = "largeCargo", -} - -export const inventorySizes = new Map([ - [Grids.Large, new Map([ - [InventoryType.CargoLarge, 421000], - [InventoryType.CargoMedium, 0], - [InventoryType.CargoSmall, 15625], - [InventoryType.Connector, 8000] - ])], - [Grids.Small, new Map([ - [InventoryType.CargoLarge, 15625], - [InventoryType.CargoMedium, 3375], - [InventoryType.CargoSmall, 125], - [InventoryType.Connector, 1152] - ])], -]); - export const metricModifiers: Map = new Map([ [1000000000, "G"], [1000000, "M"], @@ -116,17 +5,7 @@ export const metricModifiers: Map = new Map([ [1, ""] ]); -export enum Density { - Ore = "ore", - Component = "component", -} - -export const densityValues: Map = new Map([ - [Density.Ore, 1/0.37], - [Density.Component, 1/0.047], -]) - -export const localization = new Map([ +const localization = new Map([ ["space engineers", new Map([ ["en-GB", "Space Engineers"] ])], @@ -210,21 +89,21 @@ export const localization = new Map([ ["en-GB", "Large Cargo Container"], ["de-DE", "Großer Frachtcontainer"] ])], - ["fusion", new Map([ - ["en-GB", "Fusion"], - ["de-DE", "Fusion"] + ["fusionThruster", new Map([ + ["en-GB", "Fusion Thruster"], + ["de-DE", "Fusionstriebwerk"] ])], - ["hydrogen", new Map([ - ["en-GB", "Hydrogen"], - ["de-DE", "Wasserstoff"] + ["hydrogenThruster", new Map([ + ["en-GB", "Hydrogen Thruster"], + ["de-DE", "Wasserstofftriebwerk"] ])], - ["ion", new Map([ - ["en-GB", "Ion"], - ["de-DE", "Ionen"] + ["ionThruster", new Map([ + ["en-GB", "Ion Thruster"], + ["de-DE", "Ionentriebwerk"] ])], - ["atmos", new Map([ - ["en-GB", "Atmospheric"], - ["de-DE", "Atmosphären"] + ["atmosphericThruster", new Map([ + ["en-GB", "Atmospheric Thruster"], + ["de-DE", "Atmosphärentriebwerk"] ])], ["addInventory", new Map([ ["en-GB", "Add Inventory"], @@ -278,9 +157,9 @@ export const localization = new Map([ ["en-GB", "Ore"], ["de-DE", "Erz"] ])], - ["component", new Map([ - ["en-GB", "Component"], - ["de-DE", "Komponente"] + ["platinumIngot", new Map([ + ["en-GB", "Platinum Ingot"], + ["de-DE", "Platinbarren"] ])], ["density", new Map([ ["en-GB", "Density"], @@ -292,7 +171,72 @@ export const localization = new Map([ ])], ]) -export type Thruster = { - type: ThrusterType, - size: ThrusterSize + +export class Localization { + dictionary: Map>; + language: string; + + constructor(language: string) { + this.language = language; + this.dictionary = localization; + }; + + localize(key: string): string { + let localizationObject = this.dictionary.get(key) + + if (typeof localizationObject === "undefined") { + return `missing text: ${key}` + } + else { + let localizedText = localizationObject.get(this.language) + if (typeof localizedText === "undefined") { + return localizationObject.get("en-GB") || `mising text: ${key}`; + } + else { + return localizedText + } + } + } +} + +export function getFromLocalStorage(key: string) { + let val = localStorage.getItem(key); + if (val !== null && typeof val !== "undefined" && val !== '{}') { + return { result: true, value: val }; + } + else { + return { result: false, value: undefined }; + } +} + +export function applyUnits(i18n: Localization, value: number, unit: string): string { + for (const [power, modifier] of [...metricModifiers.entries()]) { + if (value > power) { + if (value / power >= 10000) { + let base = value / power; + let rest = base % 1000; + base = (base - rest) / 1000; + rest = Math.round((rest + Number.EPSILON) * 100) / 100 + return `${base}${i18n.localize("separator")}${rest}${modifier}${unit}` + } + else { + let rounded = Math.round(((value / power) + Number.EPSILON) * 100) / 100 + return `${rounded}${modifier}${unit}` + } + } + } + if (value < 0) { + return `-${applyUnits(i18n,value * -1, unit)}` + } + let rounded = Math.round(((value + Number.EPSILON) * 100) / 100) + return `${rounded}${unit}` +} + +export function weightConversion(i18n: Localization, weight: number): string { + if (weight > 1000 || weight < -1000) { + return applyUnits(i18n, weight/1000, "t") + } + else { + return `${weight.toFixed(2)}kg` + } } \ No newline at end of file diff --git a/src/lib/containers.svelte.ts b/src/lib/containers.svelte.ts new file mode 100644 index 0000000..b3dff58 --- /dev/null +++ b/src/lib/containers.svelte.ts @@ -0,0 +1,62 @@ +import {Grid} from "$lib/grid"; +import type {ObjectValues} from "$lib/components/object-values"; +import {THRUSTER_LIST, THRUSTER_TYPE_LIST} from "$lib/thruster.svelte"; +import {applyUnits} from "$lib/constants"; + +type InventoryDetails = { + key: string, + name: string, + capacity: Map +} + +export const INVENTORIES: { [key: string]: InventoryDetails } = { + CargoLarge: { + key: "CargoLarge", + name: "largeCargo", + capacity: new Map([ + [Grid.Small, 15625], + [Grid.Large, 421000], + ]) + }, + CargoMedium: { + key: "CargoMedium", + name: "mediumCargo", + capacity: new Map([ + [Grid.Small, 3375], + ]) + }, + CargoSmall: { + key: "CargoSmall", + name: "smallCargo", + capacity: new Map([ + [Grid.Small, 125], + [Grid.Large, 15625], + ]) + }, + Connector: { + key: "Connector", + name: "connector", + capacity: new Map([ + [Grid.Small, 1152], + [Grid.Large, 8000], + ]) + } +} + +type InventoryList = ObjectValues; + +export class Inventory { + details: InventoryDetails; + + constructor(details: InventoryDetails) { + if (typeof details === "undefined") { + throw("Inventory undefined, cannot create Object"); + } + this.details = details; + } + + getVolume(grid: Grid, multiplier: number): number { + console.log(this.details.capacity.get(grid), multiplier); + return (this.details.capacity.get(grid) || 0) * multiplier; + } +} \ No newline at end of file diff --git a/src/lib/fuel.ts b/src/lib/fuel.ts new file mode 100644 index 0000000..e0a7433 --- /dev/null +++ b/src/lib/fuel.ts @@ -0,0 +1,13 @@ +export class Fuel { + static readonly Electricity: Fuel = new Fuel('electric', 'W'); + static readonly Hydrogen: Fuel = new Fuel('hydrogen', 'l'); + static readonly Deuterium: Fuel = new Fuel('deuterium', 'l'); + + readonly unit: string; + readonly name: string; + + private constructor(name: string, unit: string) { + this.name = name; + this.unit = unit; + } +} \ No newline at end of file diff --git a/src/lib/grid.ts b/src/lib/grid.ts new file mode 100644 index 0000000..0bdf8f1 --- /dev/null +++ b/src/lib/grid.ts @@ -0,0 +1,4 @@ +export enum Grid { + Small = "small", + Large = "large", +} diff --git a/src/lib/materials.ts b/src/lib/materials.ts new file mode 100644 index 0000000..1104bea --- /dev/null +++ b/src/lib/materials.ts @@ -0,0 +1,26 @@ +export class CargoMaterial { + static readonly Ore: CargoMaterial = new CargoMaterial('ore', 1/0.37); + static readonly PlatinumIngot: CargoMaterial = new CargoMaterial('platinumIngot', 1/0.047); + + readonly density: number; + readonly name: string; + + private constructor(name: string, density: number) { + this.name = name; + this.density = density; + } + + static load(name: string) { + let ret = CargoMaterial.Ore; + Object.values(CargoMaterial).forEach((material) => { + if (material.name === name) { + ret = material; + } + }) + return ret; + } + + save() { + return this.name; + } +} \ No newline at end of file diff --git a/src/lib/ship.svelte.ts b/src/lib/ship.svelte.ts new file mode 100644 index 0000000..380ad80 --- /dev/null +++ b/src/lib/ship.svelte.ts @@ -0,0 +1,90 @@ +import {Thruster, THRUSTER_LIST} from "$lib/thruster.svelte"; +import {Grid} from "$lib/grid"; +import {INVENTORIES, Inventory} from "$lib/containers.svelte"; + +export class Ship { + thrusters: Array = $state([]); + inventories: Array = $state([]); + grid: Grid = $state(Grid.Small); + weight: number = $state(0); + + constructor(grid: Grid = Grid.Small) { + this.grid = grid; + } + + save() { + return { + thrusters: this.thrusters.map((thruster) => { + return thruster.details.key; + }), + inventories: this.inventories.map((inventory) => { + return inventory.details.key; + }), + grid: this.grid, + weight: this.weight, + } + } + + load(ship: { + grid: Grid, + thrusters: Array, + inventories: Array, + weight: number, + }) { + if (ship.grid !== undefined) { + this.grid = ship.grid; + } + + if (ship.thrusters !== undefined) { + this.thrusters = ship.thrusters.map((thruster) => { + return new Thruster(THRUSTER_LIST[thruster]); + }); + } + + if (ship.inventories !== undefined) { + this.inventories = ship.inventories.map((inventory) => { + return new Inventory(INVENTORIES[inventory]); + }); + } + + if (ship.weight !== undefined) { + this.weight = ship.weight; + } + } + + addThruster(thruster: Thruster): void { + this.thrusters.push(thruster); + } + + addInventory(inventory: Inventory): void { + this.inventories.push(inventory); + } + + getTotalVolume(inventoryMultiplier: number) { + let volume = 0; + this.inventories.forEach((inventory) => { + volume += inventory.getVolume(this.grid, inventoryMultiplier) + }); + return volume; + } + + spliceInventories(index: number, length: number): void { + this.inventories.splice(index, length); + } + + getTotalThrust(atmosphere: number): number { + let thrust: number = 0; + this.thrusters.forEach((thruster) => { + thrust += thruster.getThrust(this.grid, atmosphere); + }); + return thrust; + } + + getTotalMaxThrust(): number { + let thrust = 0; + this.thrusters.forEach((thruster) => { + thrust += thruster.getMaxThrust(this.grid); + }); + return thrust; + } +} \ No newline at end of file diff --git a/src/lib/thruster.svelte.ts b/src/lib/thruster.svelte.ts new file mode 100644 index 0000000..5f3e781 --- /dev/null +++ b/src/lib/thruster.svelte.ts @@ -0,0 +1,267 @@ +import {Fuel} from "$lib/fuel"; +import {Grid} from "$lib/grid"; +import type {ObjectValues} from "$lib/components/object-values"; + +export enum ThrusterSize { + Small = "smallThruster", + Large = "largeThruster", + Huge = "hugeThruster", +} + +type ThrusterTypeDetails = { + key: string, + name: string, + vacuum: number, + atmosphere: number, + fuel: Fuel, +}; + +export const THRUSTER_TYPE_LIST: { [key: string]: ThrusterTypeDetails } = { + Atmospheric: { + key: "Atmospheric", + name: "atmosphericThruster", + vacuum: 0, + atmosphere: 1, + fuel: Fuel.Electricity, + }, + Ion: { + key: "Ion", + name: "ionThruster", + vacuum: 1, + atmosphere: 0.2, + fuel: Fuel.Electricity, + }, + Hydrogen: { + key: "Hydrogen", + name: "hydrogenThruster", + vacuum: 1, + atmosphere: 1, + fuel: Fuel.Hydrogen, + }, + Fusion: { + key: "Fusion", + name: "fusionThruster", + vacuum: 1, + atmosphere: 0.5, + fuel: Fuel.Deuterium, + }, +} + +export class ThrusterType { + details: ThrusterTypeDetails = $state(THRUSTER_TYPE_LIST.Atmospheric); + + constructor(type: ThrusterTypeDetails) { + if (typeof type === "undefined") { + throw("ThrusterType undefined, cannot create Object"); + } + this.details = type; + } + + equals(obj: ThrusterType) { + let equals: Array = []; + equals[0] = this.details.key === obj.details.key; + equals[1] = this.details.name === obj.details.name; + equals[2] = this.details.vacuum === obj.details.vacuum; + equals[3] = this.details.atmosphere === obj.details.atmosphere; + equals[4] = this.details.fuel === obj.details.fuel; + return !equals.includes(false); + } +} + +type ThrusterDetails = { + key: string, + name: string, + type: ThrusterType, + size: ThrusterSize, + fuelConsumption: Map; + thrust: Map; +} + +export const THRUSTER_LIST: {[key: string]: ThrusterDetails } = { + SmallAtmos: { + key: "SmallAtmos", + name: "smallAtmos", + type: new ThrusterType(THRUSTER_TYPE_LIST.Atmospheric), + size: ThrusterSize.Small, + fuelConsumption: new Map([ + [Grid.Small, 0], + [Grid.Large, 0], + ]), + thrust: new Map([ + [Grid.Small, 65000], + [Grid.Large, 350000], + ]) + }, + LargeAtmos: { + key: "LargeAtmos", + name: "largeAtmos", + type: new ThrusterType(THRUSTER_TYPE_LIST.Atmospheric), + size: ThrusterSize.Large, + fuelConsumption: new Map([ + [Grid.Small, 0], + [Grid.Large, 0], + ]), + thrust: new Map([ + [Grid.Small, 340000], + [Grid.Large, 4500000], + ]) + }, + + SmallIon: { + key: "SmallIon", + name: "smallIon", + type: new ThrusterType(THRUSTER_TYPE_LIST.Ion), + size: ThrusterSize.Small, + fuelConsumption: new Map([ + [Grid.Small, 0], + [Grid.Large, 0], + ]), + thrust: new Map([ + [Grid.Small, 14400], + [Grid.Large, 345600], + ]) + }, + LargeIon: { + key: "LargeIon", + name: "largeIon", + type: new ThrusterType(THRUSTER_TYPE_LIST.Ion), + size: ThrusterSize.Large, + fuelConsumption: new Map([ + [Grid.Small, 0], + [Grid.Large, 0], + ]), + thrust: new Map([ + [Grid.Small, 172800], + [Grid.Large, 4320000], + ]) + }, + + SmallHydrogen: { + key: "SmallHydrogen", + name: "smallHydrogen", + type: new ThrusterType(THRUSTER_TYPE_LIST.Hydrogen), + size: ThrusterSize.Small, + fuelConsumption: new Map([ + [Grid.Small, 0], + [Grid.Large, 0], + ]), + thrust: new Map([ + [Grid.Small, 98400], + [Grid.Large, 1080000], + ]) + }, + LargeHydrogen: { + key: "LargeHydrogen", + name: "largeHydrogen", + type: new ThrusterType(THRUSTER_TYPE_LIST.Hydrogen), + size: ThrusterSize.Large, + fuelConsumption: new Map([ + [Grid.Small, 0], + [Grid.Large, 0], + ]), + thrust: new Map([ + [Grid.Small, 480000], + [Grid.Large, 7200000], + ]) + }, + + SmallFusion: { + key: "SmallFusion", + name: "smallFusion", + type: new ThrusterType(THRUSTER_TYPE_LIST.Fusion), + size: ThrusterSize.Small, + fuelConsumption: new Map([ + [Grid.Small, 0], + [Grid.Large, 0], + ]), + thrust: new Map([ + [Grid.Small, 210000], + [Grid.Large, 9040000], + ]) + }, + LargeFusion: { + key: "LargeFusion", + name: "largeFusion", + type: new ThrusterType(THRUSTER_TYPE_LIST.Fusion), + size: ThrusterSize.Large, + fuelConsumption: new Map([ + [Grid.Small, 0], + [Grid.Large, 0], + ]), + thrust: new Map([ + [Grid.Small, 1030000], + [Grid.Large, 33780000], + ]) + }, + HugeFusion: { + key: "HugeFusion", + name: "hugeFusion", + type: new ThrusterType(THRUSTER_TYPE_LIST.Fusion), + size: ThrusterSize.Huge, + fuelConsumption: new Map([ + [Grid.Small, 0], + ]), + thrust: new Map([ + [Grid.Small, 9040000], + ]) + } +} + +export class Thruster { + details: ThrusterDetails; + + constructor(thruster: ThrusterDetails) { + if (typeof thruster === "undefined") { + throw("Thruster undefined, cannot create Object"); + } + this.details = thruster; + } + + equals(obj: Thruster): boolean { + let equals: Array = []; + equals[0] = this.details.key === obj.details.key; + equals[1] = this.details.name === obj.details.name; + equals[2] = this.details.type === obj.details.type; + equals[3] = this.details.size === obj.details.size; + equals[4] = this.details.fuelConsumption === obj.details.fuelConsumption; + equals[5] = this.details.thrust === obj.details.thrust; + return !equals.includes(false); + } + + getThrust(grid: Grid, atmosphereDensity: number): number { + let efficiencyCoefficient: number = (this.details.type.details.vacuum * (1 - atmosphereDensity)) + (this.details.type.details.atmosphere * atmosphereDensity); + let thruster: ThrusterDetails | undefined = THRUSTER_LIST[this.details.key]; + if (thruster === undefined) { + throw(`Thruster ${this.details.key} undefined, cannot retrieve thrust values`); + } + let thrust: number | undefined = thruster.thrust.get(grid); + if (thrust === undefined) { + console.warn(`Thruster ${this.details.key} has no thrust values. Defaulting to 0`); + thrust = 0; + } + return thrust * efficiencyCoefficient; + } + + getMaxThrust(grid: Grid): number { + let thruster: ThrusterDetails | undefined = THRUSTER_LIST[this.details.key]; + if (thruster === undefined) { + throw("Thruster undefined, cannot retrieve thrust values"); + } + let thrust: number | undefined = thruster.thrust.get(grid); + if (thrust === undefined) { + console.warn(`Thruster ${this.details.key} has no thrust values. Defaulting to 0`); + thrust = 0; + } + return thrust; + } + + static getByType(type: ThrusterType, grid: Array = Object.values(Grid)): Array { + let thrusters: Array = []; + Object.values(THRUSTER_LIST).forEach((thruster) => { + if (thruster.type.details.key === type.details.key) { + thrusters.push(thruster); + } + }) + return thrusters; + } +} \ No newline at end of file diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index ef6c2b8..24c2548 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,3 +1,7 @@ + + - \ No newline at end of file + \ No newline at end of file diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index e19fefa..8acdc7c 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -4,34 +4,32 @@ import * as Card from "$lib/components/ui/card"; import {Button} from "$lib/components/ui/button"; import { - Grids, - inventorySizes, - InventoryType, - localization, metricModifiers, type Thruster, - ThrusterSize, - ThrusterType, - thrusterDetails, Density, densityValues, ThrusterTypeDetails, ThrusterSizeDetails + applyUnits, + getFromLocalStorage, + Localization, weightConversion } from "$lib/constants"; import {Input} from "$lib/components/ui/input"; import {Label} from "$lib/components/ui/label"; import {Separator} from "$lib/components/ui/separator"; import * as DropdownMenu from "$lib/components/ui/dropdown-menu"; import {onMount} from "svelte"; + import {CargoMaterial} from "$lib/materials"; + import ThrusterList from "$lib/components/ThrusterList.svelte"; + import {Ship} from "$lib/ship.svelte"; + import {Grid} from "$lib/grid"; + import NewThruster from "$lib/components/NewThruster.svelte"; + import NewInventory from "$lib/components/NewInventory.svelte"; + import {Inventory} from "$lib/containers.svelte"; + import InventoryList from "$lib/components/InventoryList.svelte"; - let locale = $state("en-GB"); + let i18n = $state(new Localization("en-GB")); let mounted = $state(false); - let thrusters: Array = $state([]) + let ship = $state(new Ship(Grid.Small)); $effect(() => { + ship.thrusters; if (mounted) { - localStorage.setItem("thrusters", JSON.stringify(thrusters)); - } - }) - - let inventories: Array = $state([]) - $effect(() => { - if (mounted) { - localStorage.setItem("inventories", JSON.stringify(inventories)); + localStorage.setItem("ship", JSON.stringify(ship.save())); } }) @@ -41,12 +39,6 @@ localStorage.setItem("inventoryMultiplier", inventoryMultiplier); } }) - let gridSize: Grids = $state(Grids.Small); - $effect(() => { - if (mounted) { - localStorage.setItem("gridSize", gridSize); - } - }) let gravity: number = $state(1); $effect(() => { @@ -55,10 +47,10 @@ } }) - let density: Density = $state(Density.Ore); + let material: CargoMaterial = $state(CargoMaterial.Ore); $effect(() => { if (mounted) { - localStorage.setItem("density", density); + localStorage.setItem("density", JSON.stringify(material.save())); } }) @@ -69,157 +61,53 @@ } }) - let newThruster: Thruster = $state({ - type: ThrusterType.Atmospheric, - size: ThrusterSize.Small, - }) - $effect(() => { - if (mounted) { - localStorage.setItem("newThruster", JSON.stringify(newThruster)) - } - }) + let maxWeight: number = $derived(ship.getTotalMaxThrust() / (gravity * 9.81)) - let newInventory: InventoryType = $state(InventoryType.CargoMedium) - $effect(() => { - if (mounted) { - localStorage.setItem("newInventory", JSON.stringify(newInventory)) - } - }) + let maxVehicleWeight: number = $derived(maxWeight - ship.getTotalVolume(inventoryMultiplier) * material.density) + $inspect(maxVehicleWeight); + $inspect(`${maxWeight} - ${ship.getTotalVolume(inventoryMultiplier)} * ${material.density} = ${maxVehicleWeight}`) - let totalThrust: number = $derived.by(() => { - let thrust = 0; - thrusters.forEach((thruster) => { - thrust += getThrust(thruster) - }) - return thrust - }); - let totalVolume: number = $derived.by(() => { - let volume = 0; - inventories.forEach((inventory) => { - volume += getInventoryVolume(inventory); - }) - return volume; - }) - - let maxWeight: number = $derived(totalThrust / (gravity * 9.81)) - - let maxVehicleWeight: number = $derived(maxWeight - totalVolume * densityValues.get(density)) - - function weightConversion(weight: number): string { - if (weight > 1000 || weight < -1000) { - return applyUnits(weight/1000, "t") - } - else { - return `${weight.toFixed(2)}kg` - } + function addInventory(newInventory: Inventory) { + ship.addInventory(newInventory); } - function getInventoryVolume(inventory: InventoryType): number { - return inventorySizes.get(gridSize).get(inventory) * inventoryMultiplier - } - - function getThrusterDetails(thruster: Thruster): ThrusterSizeDetails { - return thrusterDetails.get(gridSize).get(thruster.type).sizes.get(thruster.size) - } - - function getThrust(thruster: Thruster): number { - let typeDetails = getThrusterTypeDetails(thruster); - let sizeDetails = getThrusterDetails(thruster); - let thrustEfficiency = (typeDetails.vacuumFactor * (1 - atmosphericDensity)) + (typeDetails.atmosphericFactor * atmosphericDensity); - return sizeDetails.thrust * thrustEfficiency; - } - - function getThrusterTypeDetails(thruster: Thruster): ThrusterTypeDetails { - return thrusterDetails.get(gridSize).get(thruster.type) - } - - function addThruster() { - thrusters.push({ type: newThruster.type, size: newThruster.size}); - } - - function addInventory() { - inventories.push(newInventory); - } - - function localized(key: string): string { - let localizationObject = localization.get(key) - - if (typeof localizationObject === "undefined") { - return `missing text: ${key}` - } - else { - let localizedText = localizationObject.get(locale) - if (typeof localizedText === "undefined") { - return localizationObject.get("en-GB") - } - else { - return localizedText - } - } - } - - function applyUnits(value: number, unit: string) { - for (const [power, modifier] of [...metricModifiers.entries()]) { - if (value > power) { - if (value / power >= 10000) { - let base = value / power; - let rest = base % 1000; - base = (base - rest) / 1000; - rest = Math.round((rest + Number.EPSILON) * 100) / 100 - return `${base}${localized("separator")}${rest}${modifier}${unit}` - } - else { - let rounded = Math.round(((value / power) + Number.EPSILON) * 100) / 100 - return `${rounded}${modifier}${unit}` - } - } - } - if (value < 0) { - return `-${applyUnits(value * -1, unit)}` - } - let rounded = Math.round(((value + Number.EPSILON) * 100) / 100) - return `${rounded}${unit}` + function addThruster(newThruster: Thruster) { + ship.addThruster(newThruster); } onMount(() => { if (navigator) { - locale = navigator.language; + i18n.language = navigator.language; } - if (localStorage.getItem("thrusters") !== null) { - thrusters = JSON.parse(localStorage.getItem("thrusters")) + let ret = getFromLocalStorage("ship"); + if (ret.result) { + ship.load(JSON.parse(ret.value)); } - if (localStorage.getItem("inventories") !== null) { - inventories = JSON.parse(localStorage.getItem("inventories")) + ret = getFromLocalStorage("gravity"); + if (ret.result) { + gravity = ret.value; } - if (localStorage.getItem("gridSize") !== null) { - gridSize = localStorage.getItem("gridSize") + ret = getFromLocalStorage("density"); + if (ret.result) { + let parsed = JSON.parse(ret.value); + Object.values(CargoMaterial).forEach((cargoMaterial) => { + if (cargoMaterial.name === parsed) { + material = cargoMaterial + } + }) } - if (localStorage.getItem("gravity") !== null) { - gravity = localStorage.getItem("gravity") + ret = getFromLocalStorage("atmosphericDensity"); + if (ret.result) { + atmosphericDensity = ret.value; } - if (localStorage.getItem("density") !== null) { - density = localStorage.getItem("density") - } - - if (localStorage.getItem("atmosphericDensity") !== null) { - atmosphericDensity = localStorage.getItem("atmosphericDensity") - } - - if (localStorage.getItem("inventoryMultiplier") !== null) { - inventoryMultiplier = localStorage.getItem("inventoryMultiplier") - } - - if (localStorage.getItem("newThruster") !== null) { - newThruster = JSON.parse(localStorage.getItem("newThruster")) - } - - if (localStorage.getItem("newInventory") !== null) { - newInventory = JSON.parse(localStorage.getItem("newInventory")) + ret = getFromLocalStorage("inventoryMultiplier"); + if (ret.result) { + inventoryMultiplier = ret.value; } mounted = true; @@ -227,134 +115,91 @@ - {localized("title")} + {i18n.localize("title")} -
- +
+ - {localized("title")} + {i18n.localize("title")} - + - + - -
- {#each Object.values(Grids) as size} - {#if gridSize === size} - + +
+ {#each Object.values(Grid) as size} + {#if ship.grid === size} + {:else} - + {/if} {/each}
- -
- {#each Object.values(Density) as value} - {#if density === value} - + +
+ {#each Object.values(CargoMaterial) as value} + {#if material === value} + {:else} - + {/if} {/each}
-

{localized("liftableVehcileWeight")}: {weightConversion(maxVehicleWeight)}

-

{localized("liftableWeight")}: {weightConversion(maxWeight)}

+

{i18n.localize("liftableVehcileWeight")}: {weightConversion(i18n, maxVehicleWeight)}

+

{i18n.localize("liftableWeight")}: {weightConversion(i18n, maxWeight)}

- + - {localized("thrusterSettings")} + {i18n.localize("thrusterSettings")} - - {localized(newThruster.type)} - - - {#each Object.values(ThrusterType) as thrusterType} - {localized(thrusterType)} - {/each} - - - - - {localized(newThruster.size)} - - - {#each getThrusterTypeDetails(newThruster).sizes.keys() as thrusterDetails} - {localized(thrusterDetails)} - {/each} - - - - + - - + - {localized("inventorySettings")} + {i18n.localize("inventorySettings")} - + -
- {#each Object.values(InventoryType) as inventory} - {#if newInventory === inventory} - - {:else} - - {/if} - {/each} -
- +
-