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("thrusters")} ({applyUnits(totalThrust, "N")})
+ {i18n.localize("thrusters")} ({applyUnits(i18n, ship.getTotalThrust(atmosphericDensity), "N")})
-
+
-
- {#each thrusters as thruster, index}
-
- - {localized(thruster.size)} {localized(thruster.type)} {localized("thruster")}: {applyUnits(getThrust(thruster), "N")}
-
-
- {/each}
-
+
-
+
- {localized("inventorySettings")}
+ {i18n.localize("inventorySettings")}
-
+
-
- {#each Object.values(InventoryType) as inventory}
- {#if newInventory === inventory}
-
- {:else}
-
- {/if}
- {/each}
-
-
+
-
+
- {localized("inventories")} ({applyUnits(totalVolume, "l")})
+ {i18n.localize("inventories")} ({applyUnits(i18n, ship.getTotalVolume(inventoryMultiplier), "l")})
-
+
-
- {#each inventories as inventory, index}
-
- - {localized(inventory)} {localized("volume")}: {applyUnits(getInventoryVolume(inventory), "l")}
-
-
- {/each}
-
+