Major Rewrite of underlying code
This commit is contained in:
parent
d031e2b7a1
commit
c7fa40b454
15 changed files with 923 additions and 437 deletions
101
src/app.css
101
src/app.css
|
@ -3,68 +3,49 @@
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--background: 0 0% 100%;
|
--background: 239 19% 95%;
|
||||||
--foreground: 222.2 84% 4.9%;
|
--foreground: 239 5% 0%;
|
||||||
|
--card: 239 19% 90%;
|
||||||
--muted: 210 40% 96.1%;
|
--card-foreground: 239 5% 10%;
|
||||||
--muted-foreground: 215.4 16.3% 46.9%;
|
--popover: 239 19% 95%;
|
||||||
|
--popover-foreground: 239 95% 0%;
|
||||||
--popover: 0 0% 100%;
|
--primary: 239 58% 35%;
|
||||||
--popover-foreground: 222.2 84% 4.9%;
|
--primary-foreground: 0 0% 100%;
|
||||||
|
--secondary: 239 19% 70%;
|
||||||
--card: 0 0% 100%;
|
--secondary-foreground: 0 0% 0%;
|
||||||
--card-foreground: 222.2 84% 4.9%;
|
--muted: 201 19% 85%;
|
||||||
|
--muted-foreground: 239 5% 35%;
|
||||||
--border: 214.3 31.8% 91.4%;
|
--accent: 201 19% 80%;
|
||||||
--input: 214.3 31.8% 91.4%;
|
--accent-foreground: 239 5% 10%;
|
||||||
|
--destructive: 0 50% 30%;
|
||||||
--primary: 222.2 47.4% 11.2%;
|
--destructive-foreground: 239 5% 90%;
|
||||||
--primary-foreground: 210 40% 98%;
|
--border: 239 20% 50%;
|
||||||
|
--input: 239 20% 18%;
|
||||||
--secondary: 210 40% 96.1%;
|
--ring: 239 58% 35%;
|
||||||
--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%;
|
|
||||||
|
|
||||||
--radius: 0.5rem;
|
--radius: 0.5rem;
|
||||||
}
|
}
|
||||||
|
.dark {
|
||||||
.dark {
|
--background: 239 19% 5%;
|
||||||
--background: 222.2 84% 4.9%;
|
--foreground: 239 5% 90%;
|
||||||
--foreground: 210 40% 98%;
|
--card: 239 19% 0%;
|
||||||
|
--card-foreground: 239 5% 90%;
|
||||||
--muted: 217.2 32.6% 17.5%;
|
--popover: 239 19% 5%;
|
||||||
--muted-foreground: 215 20.2% 65.1%;
|
--popover-foreground: 239 5% 90%;
|
||||||
|
--primary: 239 58% 35%;
|
||||||
--popover: 222.2 84% 4.9%;
|
--primary-foreground: 0 0% 100%;
|
||||||
--popover-foreground: 210 40% 98%;
|
--secondary: 239 19% 10%;
|
||||||
|
--secondary-foreground: 0 0% 100%;
|
||||||
--card: 222.2 84% 4.9%;
|
--muted: 201 19% 15%;
|
||||||
--card-foreground: 210 40% 98%;
|
--muted-foreground: 239 5% 60%;
|
||||||
|
--accent: 201 19% 15%;
|
||||||
--border: 217.2 32.6% 17.5%;
|
--accent-foreground: 239 5% 90%;
|
||||||
--input: 217.2 32.6% 17.5%;
|
--destructive: 0 50% 30%;
|
||||||
|
--destructive-foreground: 239 5% 90%;
|
||||||
--primary: 210 40% 98%;
|
--border: 239 20% 18%;
|
||||||
--primary-foreground: 222.2 47.4% 11.2%;
|
--input: 239 20% 18%;
|
||||||
|
--ring: 239 58% 35%;
|
||||||
--secondary: 217.2 32.6% 17.5%;
|
--radius: 0.5rem;
|
||||||
--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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
34
src/lib/components/InventoryList.svelte
Normal file
34
src/lib/components/InventoryList.svelte
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<svelte:options runes />
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import {applyUnits} from "$lib/constants.js";
|
||||||
|
import {Button} from "$lib/components/ui/button/index.js";
|
||||||
|
import {Grid} from "$lib/grid";
|
||||||
|
|
||||||
|
let { i18n = new Localization("en-GB"), inventories = $bindable(), grid, multiplier } = $props();
|
||||||
|
let valid = $derived.by(() => {
|
||||||
|
let valids = [];
|
||||||
|
valids[0] = typeof inventories !== "undefined";
|
||||||
|
valids[1] = typeof grid !== "undefined";
|
||||||
|
valids[2] = typeof multiplier !== "undefined";
|
||||||
|
return !valids.includes(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
function removeInventory(index: number) {
|
||||||
|
thrusters.splice(index, 1);
|
||||||
|
}
|
||||||
|
$inspect(inventories)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="max-h-full flex flex-col gap-2 overflow-y-auto">
|
||||||
|
{#if valid}
|
||||||
|
{#each inventories as inventory, index}
|
||||||
|
<p class="flex gap-2 justify-between">
|
||||||
|
- {i18n.localize(inventory.details.name)} {i18n.localize("volume")}: {applyUnits(i18n, inventory.getVolume(grid, multiplier), "l")}
|
||||||
|
<Button variant="destructive" onclick={() => removeInventory(index)}>X</Button>
|
||||||
|
</p>
|
||||||
|
{/each}
|
||||||
|
{:else}
|
||||||
|
<p>Invalid Props</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
66
src/lib/components/NewInventory.svelte
Normal file
66
src/lib/components/NewInventory.svelte
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
<svelte:options runes />
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import {getFromLocalStorage, Localization} from "$lib/constants.js";
|
||||||
|
import {Button} from "$lib/components/ui/button/index.js";
|
||||||
|
import {Grid} from "$lib/grid";
|
||||||
|
import * as DropdownMenu from "$lib/components/ui/dropdown-menu";
|
||||||
|
import {Inventory, INVENTORIES} from "$lib/containers.svelte";
|
||||||
|
import {THRUSTER_TYPE_LIST, ThrusterType} from "$lib/thruster.svelte";
|
||||||
|
import {onMount} from "svelte";
|
||||||
|
|
||||||
|
let { i18n = new Localization("en-GB"), onAddInventory, grid } = $props();
|
||||||
|
let mounted = $state(false);
|
||||||
|
|
||||||
|
let valid = $derived.by(() => {
|
||||||
|
let valids = [];
|
||||||
|
valids[0] = typeof onAddInventory !== "undefined";
|
||||||
|
valids[1] = typeof grid !== "undefined";
|
||||||
|
return !valids.includes(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
let key: string = $state(INVENTORIES.CargoSmall.key)
|
||||||
|
let name = $derived(INVENTORIES[key].name);
|
||||||
|
$effect(() => {
|
||||||
|
if (mounted) {
|
||||||
|
localStorage.setItem("newInventory", key)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function updateDetails(newKey: string) {
|
||||||
|
key = newKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
function construct() {
|
||||||
|
return new Inventory(INVENTORIES[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
let ret = getFromLocalStorage("newInventory");
|
||||||
|
if (ret.result) {
|
||||||
|
key = ret.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
mounted = true;
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if valid}
|
||||||
|
<div class="flex flex-col flex-wrap gap-3 max-w-fit place-self-center items-center">
|
||||||
|
<DropdownMenu.Root>
|
||||||
|
<DropdownMenu.Trigger>
|
||||||
|
<Button variant="secondary">{i18n.localize(name)}</Button>
|
||||||
|
</DropdownMenu.Trigger>
|
||||||
|
<DropdownMenu.Content>
|
||||||
|
<DropdownMenu.RadioGroup value={key} onValueChange={(change) => updateDetails(change)}>
|
||||||
|
{#each Object.values(INVENTORIES) as inventory}
|
||||||
|
<DropdownMenu.RadioItem value={inventory.key}>{i18n.localize(inventory.name)}</DropdownMenu.RadioItem>
|
||||||
|
{/each}
|
||||||
|
</DropdownMenu.RadioGroup>
|
||||||
|
</DropdownMenu.Content>
|
||||||
|
</DropdownMenu.Root>
|
||||||
|
<Button class="bg-primary max-w-fit" onclick={() => onAddInventory(construct())}>{i18n.localize("addInventory")}</Button>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<p>Invalid Props</p>
|
||||||
|
{/if}
|
115
src/lib/components/NewThruster.svelte
Normal file
115
src/lib/components/NewThruster.svelte
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
<svelte:options runes />
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import {
|
||||||
|
Thruster, THRUSTER_LIST,
|
||||||
|
THRUSTER_TYPE_LIST,
|
||||||
|
ThrusterSize,
|
||||||
|
ThrusterType
|
||||||
|
} from "$lib/thruster.svelte";
|
||||||
|
import {onMount} from "svelte";
|
||||||
|
import * as DropdownMenu from "$lib/components/ui/dropdown-menu";
|
||||||
|
import {getFromLocalStorage, Localization} from "$lib/constants";
|
||||||
|
import {Button} from "$lib/components/ui/button";
|
||||||
|
import {Grid} from "$lib/grid";
|
||||||
|
|
||||||
|
let { i18n = new Localization("en-GB"), onAddThruster, grid = Grid.Small } = $props();
|
||||||
|
let mounted = $state(false);
|
||||||
|
|
||||||
|
let valid = $derived.by(() => {
|
||||||
|
let valids = [];
|
||||||
|
valids[0] = typeof onAddThruster !== "undefined";
|
||||||
|
valids[1] = typeof grid !== "undefined";
|
||||||
|
return !valids.includes(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
let type: ThrusterType = $state(new ThrusterType(THRUSTER_TYPE_LIST.Atmospheric));
|
||||||
|
$effect(() => {
|
||||||
|
if (mounted) {
|
||||||
|
localStorage.setItem("newThrusterType", type.details.key);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
let size = $state(ThrusterSize.Small);
|
||||||
|
$effect(() => {
|
||||||
|
if (mounted) {
|
||||||
|
localStorage.setItem("newThrusterSize", size)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
let sizes: Array<ThrusterSize> = $derived(Thruster.getByType(type, size).map((thruster) => {return thruster.size}));
|
||||||
|
$effect(() => {
|
||||||
|
if (!sizes.includes(size)) {
|
||||||
|
size = sizes[0]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function construct() {
|
||||||
|
let newThruster;
|
||||||
|
Object.values(THRUSTER_LIST).forEach((thruster) => {
|
||||||
|
if (thruster.type.equals(type) && thruster.size === size) {
|
||||||
|
newThruster = new Thruster(thruster);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return newThruster;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateDetails(newKey: string) {
|
||||||
|
type.details = THRUSTER_TYPE_LIST[newKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
let ret = getFromLocalStorage("newThrusterType");
|
||||||
|
if (ret.result) {
|
||||||
|
type = new ThrusterType(THRUSTER_TYPE_LIST[ret.value]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = getFromLocalStorage("newThrusterSize");
|
||||||
|
if (ret.result) {
|
||||||
|
size = ret.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
mounted = true;
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-3 place-self-center items-center">
|
||||||
|
{#if valid}
|
||||||
|
<div class="flex flex-row gap-3 flex-wrap justify-center">
|
||||||
|
<div>
|
||||||
|
<DropdownMenu.Root>
|
||||||
|
<DropdownMenu.Trigger>
|
||||||
|
<Button variant="secondary">
|
||||||
|
{i18n.localize(size)}
|
||||||
|
</Button>
|
||||||
|
</DropdownMenu.Trigger>
|
||||||
|
<DropdownMenu.Content>
|
||||||
|
<DropdownMenu.RadioGroup bind:value={size}>
|
||||||
|
{#each sizes as thrusterSize}
|
||||||
|
<DropdownMenu.RadioItem value={thrusterSize}>{i18n.localize(thrusterSize)}</DropdownMenu.RadioItem>
|
||||||
|
{/each}
|
||||||
|
</DropdownMenu.RadioGroup>
|
||||||
|
</DropdownMenu.Content>
|
||||||
|
</DropdownMenu.Root>
|
||||||
|
</div>
|
||||||
|
<DropdownMenu.Root>
|
||||||
|
<DropdownMenu.Trigger>
|
||||||
|
<Button variant="secondary">
|
||||||
|
{i18n.localize(type.details.name)}
|
||||||
|
</Button>
|
||||||
|
</DropdownMenu.Trigger>
|
||||||
|
<DropdownMenu.Content>
|
||||||
|
<DropdownMenu.RadioGroup value={type.details.key} onValueChange={(change) => {updateDetails(change)}}>
|
||||||
|
{#each Object.values(THRUSTER_TYPE_LIST) as thrusterType}
|
||||||
|
<DropdownMenu.RadioItem value={thrusterType.key}>{i18n.localize(thrusterType.name)}</DropdownMenu.RadioItem>
|
||||||
|
{/each}
|
||||||
|
</DropdownMenu.RadioGroup>
|
||||||
|
</DropdownMenu.Content>
|
||||||
|
</DropdownMenu.Root>
|
||||||
|
</div>
|
||||||
|
<Button vclass="bg-primary max-w-fit" onclick={() => onAddThruster(construct())}>{i18n.localize("addThruster")}</Button>
|
||||||
|
{:else}
|
||||||
|
<p>Invalid Props</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
34
src/lib/components/ThrusterList.svelte
Normal file
34
src/lib/components/ThrusterList.svelte
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<svelte:options runes />
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import {Button} from "$lib/components/ui/button/index";
|
||||||
|
import {applyUnits, Localization} from "$lib/constants";
|
||||||
|
import {Grid} from "$lib/grid";
|
||||||
|
|
||||||
|
let { i18n = new Localization("en-GB"), thrusters = $bindable(), grid, atmosphere } = $props();
|
||||||
|
let valid = $derived.by(() => {
|
||||||
|
let valids = [];
|
||||||
|
valids[0] = typeof thrusters !== "undefined";
|
||||||
|
valids[1] = typeof grid !== "undefined";
|
||||||
|
valids[2] = typeof atmosphere !== "undefined";
|
||||||
|
return !valids.includes(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
function removeThruster(index: number) {
|
||||||
|
thrusters.splice(index, 1);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="max-h-full flex flex-col gap-2 overflow-y-auto">
|
||||||
|
{#if valid}
|
||||||
|
{#each thrusters as thruster, index}
|
||||||
|
<p class="gap-2 flex justify-between">
|
||||||
|
- {i18n.localize(thruster.details.size)} {i18n.localize(thruster.details.type.details.name)}: {applyUnits(i18n, thruster.getThrust(grid, atmosphere), "N")}
|
||||||
|
<Button variant="destructive" onclick={() => removeThruster(index)}>X</Button>
|
||||||
|
</p>
|
||||||
|
{/each}
|
||||||
|
{:else}
|
||||||
|
<p>Invalid Props</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
1
src/lib/components/object-values.ts
Normal file
1
src/lib/components/object-values.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export type ObjectValues<T> = T[keyof T];
|
|
@ -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<ThrusterSize, ThrusterSizeDetails>;
|
|
||||||
|
|
||||||
constructor(atmos: number, vacuum: number, fuel: ThrusterFuel, sizes: Map<ThrusterSize, ThrusterSizeDetails>) {
|
|
||||||
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<Grids, Map<ThrusterType, ThrusterTypeDetails>> = 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<number, string> = new Map([
|
export const metricModifiers: Map<number, string> = new Map([
|
||||||
[1000000000, "G"],
|
[1000000000, "G"],
|
||||||
[1000000, "M"],
|
[1000000, "M"],
|
||||||
|
@ -116,17 +5,7 @@ export const metricModifiers: Map<number, string> = new Map([
|
||||||
[1, ""]
|
[1, ""]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export enum Density {
|
const localization = new Map([
|
||||||
Ore = "ore",
|
|
||||||
Component = "component",
|
|
||||||
}
|
|
||||||
|
|
||||||
export const densityValues: Map<Density, number> = new Map([
|
|
||||||
[Density.Ore, 1/0.37],
|
|
||||||
[Density.Component, 1/0.047],
|
|
||||||
])
|
|
||||||
|
|
||||||
export const localization = new Map([
|
|
||||||
["space engineers", new Map([
|
["space engineers", new Map([
|
||||||
["en-GB", "Space Engineers"]
|
["en-GB", "Space Engineers"]
|
||||||
])],
|
])],
|
||||||
|
@ -210,21 +89,21 @@ export const localization = new Map([
|
||||||
["en-GB", "Large Cargo Container"],
|
["en-GB", "Large Cargo Container"],
|
||||||
["de-DE", "Großer Frachtcontainer"]
|
["de-DE", "Großer Frachtcontainer"]
|
||||||
])],
|
])],
|
||||||
["fusion", new Map([
|
["fusionThruster", new Map([
|
||||||
["en-GB", "Fusion"],
|
["en-GB", "Fusion Thruster"],
|
||||||
["de-DE", "Fusion"]
|
["de-DE", "Fusionstriebwerk"]
|
||||||
])],
|
])],
|
||||||
["hydrogen", new Map([
|
["hydrogenThruster", new Map([
|
||||||
["en-GB", "Hydrogen"],
|
["en-GB", "Hydrogen Thruster"],
|
||||||
["de-DE", "Wasserstoff"]
|
["de-DE", "Wasserstofftriebwerk"]
|
||||||
])],
|
])],
|
||||||
["ion", new Map([
|
["ionThruster", new Map([
|
||||||
["en-GB", "Ion"],
|
["en-GB", "Ion Thruster"],
|
||||||
["de-DE", "Ionen"]
|
["de-DE", "Ionentriebwerk"]
|
||||||
])],
|
])],
|
||||||
["atmos", new Map([
|
["atmosphericThruster", new Map([
|
||||||
["en-GB", "Atmospheric"],
|
["en-GB", "Atmospheric Thruster"],
|
||||||
["de-DE", "Atmosphären"]
|
["de-DE", "Atmosphärentriebwerk"]
|
||||||
])],
|
])],
|
||||||
["addInventory", new Map([
|
["addInventory", new Map([
|
||||||
["en-GB", "Add Inventory"],
|
["en-GB", "Add Inventory"],
|
||||||
|
@ -278,9 +157,9 @@ export const localization = new Map([
|
||||||
["en-GB", "Ore"],
|
["en-GB", "Ore"],
|
||||||
["de-DE", "Erz"]
|
["de-DE", "Erz"]
|
||||||
])],
|
])],
|
||||||
["component", new Map([
|
["platinumIngot", new Map([
|
||||||
["en-GB", "Component"],
|
["en-GB", "Platinum Ingot"],
|
||||||
["de-DE", "Komponente"]
|
["de-DE", "Platinbarren"]
|
||||||
])],
|
])],
|
||||||
["density", new Map([
|
["density", new Map([
|
||||||
["en-GB", "Density"],
|
["en-GB", "Density"],
|
||||||
|
@ -292,7 +171,72 @@ export const localization = new Map([
|
||||||
])],
|
])],
|
||||||
])
|
])
|
||||||
|
|
||||||
export type Thruster = {
|
|
||||||
type: ThrusterType,
|
export class Localization {
|
||||||
size: ThrusterSize
|
dictionary: Map<string, Map<string, string>>;
|
||||||
|
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`
|
||||||
|
}
|
||||||
}
|
}
|
62
src/lib/containers.svelte.ts
Normal file
62
src/lib/containers.svelte.ts
Normal file
|
@ -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<Grid, number>
|
||||||
|
}
|
||||||
|
|
||||||
|
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<typeof INVENTORIES>;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
13
src/lib/fuel.ts
Normal file
13
src/lib/fuel.ts
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
4
src/lib/grid.ts
Normal file
4
src/lib/grid.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
export enum Grid {
|
||||||
|
Small = "small",
|
||||||
|
Large = "large",
|
||||||
|
}
|
26
src/lib/materials.ts
Normal file
26
src/lib/materials.ts
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
90
src/lib/ship.svelte.ts
Normal file
90
src/lib/ship.svelte.ts
Normal file
|
@ -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<Thruster> = $state([]);
|
||||||
|
inventories: Array<Inventory> = $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<string>,
|
||||||
|
inventories: Array<string>,
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
267
src/lib/thruster.svelte.ts
Normal file
267
src/lib/thruster.svelte.ts
Normal file
|
@ -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<boolean> = [];
|
||||||
|
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<Grid, number>;
|
||||||
|
thrust: Map<Grid, number>;
|
||||||
|
}
|
||||||
|
|
||||||
|
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<boolean> = [];
|
||||||
|
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<Grid> = Object.values(Grid)): Array<ThrusterDetails> {
|
||||||
|
let thrusters: Array<ThrusterDetails> = [];
|
||||||
|
Object.values(THRUSTER_LIST).forEach((thruster) => {
|
||||||
|
if (thruster.type.details.key === type.details.key) {
|
||||||
|
thrusters.push(thruster);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return thrusters;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,7 @@
|
||||||
|
<script>
|
||||||
|
import "../app.css";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<slot></slot>
|
||||||
|
|
||||||
<slot></slot><script>import "../app.css";</script><style></style>
|
<style></style>
|
|
@ -4,34 +4,32 @@
|
||||||
import * as Card from "$lib/components/ui/card";
|
import * as Card from "$lib/components/ui/card";
|
||||||
import {Button} from "$lib/components/ui/button";
|
import {Button} from "$lib/components/ui/button";
|
||||||
import {
|
import {
|
||||||
Grids,
|
applyUnits,
|
||||||
inventorySizes,
|
getFromLocalStorage,
|
||||||
InventoryType,
|
Localization, weightConversion
|
||||||
localization, metricModifiers, type Thruster,
|
|
||||||
ThrusterSize,
|
|
||||||
ThrusterType,
|
|
||||||
thrusterDetails, Density, densityValues, ThrusterTypeDetails, ThrusterSizeDetails
|
|
||||||
} from "$lib/constants";
|
} from "$lib/constants";
|
||||||
import {Input} from "$lib/components/ui/input";
|
import {Input} from "$lib/components/ui/input";
|
||||||
import {Label} from "$lib/components/ui/label";
|
import {Label} from "$lib/components/ui/label";
|
||||||
import {Separator} from "$lib/components/ui/separator";
|
import {Separator} from "$lib/components/ui/separator";
|
||||||
import * as DropdownMenu from "$lib/components/ui/dropdown-menu";
|
import * as DropdownMenu from "$lib/components/ui/dropdown-menu";
|
||||||
import {onMount} from "svelte";
|
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 mounted = $state(false);
|
||||||
|
|
||||||
let thrusters: Array<Thruster> = $state([])
|
let ship = $state(new Ship(Grid.Small));
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
|
ship.thrusters;
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
localStorage.setItem("thrusters", JSON.stringify(thrusters));
|
localStorage.setItem("ship", JSON.stringify(ship.save()));
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
let inventories: Array<InventoryType> = $state([])
|
|
||||||
$effect(() => {
|
|
||||||
if (mounted) {
|
|
||||||
localStorage.setItem("inventories", JSON.stringify(inventories));
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -41,12 +39,6 @@
|
||||||
localStorage.setItem("inventoryMultiplier", inventoryMultiplier);
|
localStorage.setItem("inventoryMultiplier", inventoryMultiplier);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
let gridSize: Grids = $state(Grids.Small);
|
|
||||||
$effect(() => {
|
|
||||||
if (mounted) {
|
|
||||||
localStorage.setItem("gridSize", gridSize);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
let gravity: number = $state(1);
|
let gravity: number = $state(1);
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
|
@ -55,10 +47,10 @@
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
let density: Density = $state(Density.Ore);
|
let material: CargoMaterial = $state(CargoMaterial.Ore);
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
localStorage.setItem("density", density);
|
localStorage.setItem("density", JSON.stringify(material.save()));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -69,157 +61,53 @@
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
let newThruster: Thruster = $state({
|
let maxWeight: number = $derived(ship.getTotalMaxThrust() / (gravity * 9.81))
|
||||||
type: ThrusterType.Atmospheric,
|
|
||||||
size: ThrusterSize.Small,
|
|
||||||
})
|
|
||||||
$effect(() => {
|
|
||||||
if (mounted) {
|
|
||||||
localStorage.setItem("newThruster", JSON.stringify(newThruster))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
let newInventory: InventoryType = $state(InventoryType.CargoMedium)
|
let maxVehicleWeight: number = $derived(maxWeight - ship.getTotalVolume(inventoryMultiplier) * material.density)
|
||||||
$effect(() => {
|
$inspect(maxVehicleWeight);
|
||||||
if (mounted) {
|
$inspect(`${maxWeight} - ${ship.getTotalVolume(inventoryMultiplier)} * ${material.density} = ${maxVehicleWeight}`)
|
||||||
localStorage.setItem("newInventory", JSON.stringify(newInventory))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
let totalThrust: number = $derived.by(() => {
|
function addInventory(newInventory: Inventory) {
|
||||||
let thrust = 0;
|
ship.addInventory(newInventory);
|
||||||
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 getInventoryVolume(inventory: InventoryType): number {
|
function addThruster(newThruster: Thruster) {
|
||||||
return inventorySizes.get(gridSize).get(inventory) * inventoryMultiplier
|
ship.addThruster(newThruster);
|
||||||
}
|
|
||||||
|
|
||||||
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}`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (navigator) {
|
if (navigator) {
|
||||||
locale = navigator.language;
|
i18n.language = navigator.language;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (localStorage.getItem("thrusters") !== null) {
|
let ret = getFromLocalStorage("ship");
|
||||||
thrusters = JSON.parse(localStorage.getItem("thrusters"))
|
if (ret.result) {
|
||||||
|
ship.load(JSON.parse(ret.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (localStorage.getItem("inventories") !== null) {
|
ret = getFromLocalStorage("gravity");
|
||||||
inventories = JSON.parse(localStorage.getItem("inventories"))
|
if (ret.result) {
|
||||||
|
gravity = ret.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (localStorage.getItem("gridSize") !== null) {
|
ret = getFromLocalStorage("density");
|
||||||
gridSize = localStorage.getItem("gridSize")
|
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) {
|
ret = getFromLocalStorage("atmosphericDensity");
|
||||||
gravity = localStorage.getItem("gravity")
|
if (ret.result) {
|
||||||
|
atmosphericDensity = ret.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (localStorage.getItem("density") !== null) {
|
ret = getFromLocalStorage("inventoryMultiplier");
|
||||||
density = localStorage.getItem("density")
|
if (ret.result) {
|
||||||
}
|
inventoryMultiplier = ret.value;
|
||||||
|
|
||||||
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"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mounted = true;
|
mounted = true;
|
||||||
|
@ -227,134 +115,91 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
<title>{localized("title")}</title>
|
<title>{i18n.localize("title")}</title>
|
||||||
<meta name="robots" content="noindex nofollow" />
|
<meta name="robots" content="noindex nofollow" />
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<div class="gap-4 grid grid-cols-3 h-full">
|
<div class="gap-4 flex flex-row flex-wrap h-full">
|
||||||
<Card.Root class="col-span-1">
|
<Card.Root class="flex-1">
|
||||||
<Card.Header>
|
<Card.Header>
|
||||||
<Card.Title>{localized("title")}</Card.Title>
|
<Card.Title>{i18n.localize("title")}</Card.Title>
|
||||||
</Card.Header>
|
</Card.Header>
|
||||||
<Card.Content class="flex flex-col gap-3">
|
<Card.Content class="flex flex-col gap-3">
|
||||||
<Separator />
|
<Separator />
|
||||||
<Label for="gravity">{localized("gravity")}</Label>
|
<Label for="gravity">{i18n.localize("gravity")}</Label>
|
||||||
<Input type="number" step="0.01" id="gravity" bind:value={gravity}/>
|
<Input type="number" step="0.01" id="gravity" bind:value={gravity}/>
|
||||||
<Label for="atmosDensity">{localized("atmosDensity")}</Label>
|
<Label for="atmosDensity">{i18n.localize("atmosDensity")}</Label>
|
||||||
<Input type="number" step="0.01" id="atmosDensity" bind:value={atmosphericDensity}/>
|
<Input type="number" step="0.01" id="atmosDensity" bind:value={atmosphericDensity}/>
|
||||||
<Separator />
|
<Separator />
|
||||||
<Label for="gridSize">{localized("gridSize")}</Label>
|
<Label for="gridSize">{i18n.localize("gridSize")}</Label>
|
||||||
<div id="gridSize" class="flex">
|
<div id="gridSize" class="flex gap-2">
|
||||||
{#each Object.values(Grids) as size}
|
{#each Object.values(Grid) as size}
|
||||||
{#if gridSize === size}
|
{#if ship.grid === size}
|
||||||
<Button variant="primary">{localized(size)}</Button>
|
<Button class="bg-primary">{i18n.localize(size)}</Button>
|
||||||
{:else}
|
{:else}
|
||||||
<Button variant="secondary" onclick={() => gridSize = size}>{localized(size)}</Button>
|
<Button variant="secondary" onclick={() => ship.grid = size}>{i18n.localize(size)}</Button>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<Separator />
|
<Separator />
|
||||||
<Label for="density">{localized("density")}</Label>
|
<Label for="density">{i18n.localize("density")}</Label>
|
||||||
<div id="density" class="flex">
|
<div id="density" class="flex gap-2">
|
||||||
{#each Object.values(Density) as value}
|
{#each Object.values(CargoMaterial) as value}
|
||||||
{#if density === value}
|
{#if material === value}
|
||||||
<Button variant="primary">{localized(value)}</Button>
|
<Button class="bg-primary">{i18n.localize(value.name)}</Button>
|
||||||
{:else}
|
{:else}
|
||||||
<Button variant="secondary" onclick={() => density = value}>{localized(value)}</Button>
|
<Button variant="secondary" onclick={() => material = value}>{i18n.localize(value.name)}</Button>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<Separator />
|
<Separator />
|
||||||
<p>{localized("liftableVehcileWeight")}: {weightConversion(maxVehicleWeight)}</p>
|
<p>{i18n.localize("liftableVehcileWeight")}: {weightConversion(i18n, maxVehicleWeight)}</p>
|
||||||
<p>{localized("liftableWeight")}: {weightConversion(maxWeight)}</p>
|
<p>{i18n.localize("liftableWeight")}: {weightConversion(i18n, maxWeight)}</p>
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
</Card.Root>
|
</Card.Root>
|
||||||
<Card.Root class="col-span-1 flex flex-col flex-grow">
|
<Card.Root class="flex-1 flex flex-col flex-grow">
|
||||||
<Card.Header>
|
<Card.Header>
|
||||||
<Card.Title>{localized("thrusterSettings")}</Card.Title>
|
<Card.Title>{i18n.localize("thrusterSettings")}</Card.Title>
|
||||||
</Card.Header>
|
</Card.Header>
|
||||||
<Card.Content class="flex flex-col flex-grow gap-3">
|
<Card.Content class="flex flex-col flex-grow gap-3">
|
||||||
<Separator />
|
<Separator />
|
||||||
<Card.Root>
|
<Card.Root>
|
||||||
<Card.Content class="flex flex-col gap-3 pt-6">
|
<Card.Content class="flex flex-col gap-3 pt-6">
|
||||||
<DropdownMenu.Root>
|
<NewThruster i18n={i18n} onAddThruster={addThruster} />
|
||||||
<DropdownMenu.Trigger>{localized(newThruster.type)}</DropdownMenu.Trigger>
|
|
||||||
<DropdownMenu.Content>
|
|
||||||
<DropdownMenu.RadioGroup bind:value={newThruster.type}>
|
|
||||||
{#each Object.values(ThrusterType) as thrusterType}
|
|
||||||
<DropdownMenu.RadioItem value={thrusterType}>{localized(thrusterType)}</DropdownMenu.RadioItem>
|
|
||||||
{/each}
|
|
||||||
</DropdownMenu.RadioGroup>
|
|
||||||
</DropdownMenu.Content>
|
|
||||||
</DropdownMenu.Root>
|
|
||||||
<DropdownMenu.Root>
|
|
||||||
<DropdownMenu.Trigger>{localized(newThruster.size)}</DropdownMenu.Trigger>
|
|
||||||
<DropdownMenu.Content>
|
|
||||||
<DropdownMenu.RadioGroup bind:value={newThruster.size}>
|
|
||||||
{#each getThrusterTypeDetails(newThruster).sizes.keys() as thrusterDetails}
|
|
||||||
<DropdownMenu.RadioItem value={thrusterDetails}>{localized(thrusterDetails)}</DropdownMenu.RadioItem>
|
|
||||||
{/each}
|
|
||||||
</DropdownMenu.RadioGroup>
|
|
||||||
</DropdownMenu.Content>
|
|
||||||
</DropdownMenu.Root>
|
|
||||||
<Button variant="secondary" onclick={() => addThruster()}>{localized("addThruster")}</Button>
|
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
</Card.Root>
|
</Card.Root>
|
||||||
<Card.Root class="flex flex-col h-0 flex-grow">
|
<Card.Root class="flex flex-col h-60 flex-grow">
|
||||||
<Card.Header>
|
<Card.Header>
|
||||||
<Card.Title>{localized("thrusters")} ({applyUnits(totalThrust, "N")})</Card.Title>
|
<Card.Title>{i18n.localize("thrusters")} ({applyUnits(i18n, ship.getTotalThrust(atmosphericDensity), "N")})</Card.Title>
|
||||||
</Card.Header>
|
</Card.Header>
|
||||||
<Card.Content class="overflow-hidden">
|
<Card.Content class="flex flex-col gap-3 overflow-hidden">
|
||||||
<Separator />
|
<Separator />
|
||||||
<div class="max-h-full overflow-y-auto">
|
<ThrusterList i18n={i18n} bind:thrusters={ship.thrusters} grid={ship.grid} atmosphere={atmosphericDensity}/>
|
||||||
{#each thrusters as thruster, index}
|
|
||||||
<p class="p-1">
|
|
||||||
- {localized(thruster.size)} {localized(thruster.type)} {localized("thruster")}: {applyUnits(getThrust(thruster), "N")}
|
|
||||||
<Button variant="destructive" onclick={() => thrusters.splice(index, 1)}>X</Button>
|
|
||||||
</p>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
</Card.Root>
|
</Card.Root>
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
</Card.Root>
|
</Card.Root>
|
||||||
|
|
||||||
<Card.Root class="col-span-1 flex flex-col flex-grow">
|
<Card.Root class="flex-1 flex flex-col flex-grow">
|
||||||
<Card.Header>
|
<Card.Header>
|
||||||
<Card.Title>{localized("inventorySettings")}</Card.Title>
|
<Card.Title>{i18n.localize("inventorySettings")}</Card.Title>
|
||||||
</Card.Header>
|
</Card.Header>
|
||||||
<Card.Content class="flex flex-col flex-grow gap-3">
|
<Card.Content class="flex flex-col flex-grow gap-3">
|
||||||
<Separator />
|
<Separator />
|
||||||
<Label for="inventorySize">{localized("inventory")} {localized("multiplier")}</Label>
|
<Label for="inventorySize">{i18n.localize("inventory")} {i18n.localize("multiplier")}</Label>
|
||||||
<Input id="inventorySize" type="number" bind:value={inventoryMultiplier}/>
|
<Input id="inventorySize" type="number" bind:value={inventoryMultiplier}/>
|
||||||
<Card.Root>
|
<Card.Root>
|
||||||
<Card.Content class="pt-6 flex flex-col gap-3">
|
<Card.Content class="pt-6 flex flex-col gap-3">
|
||||||
<div class="flex gap-2 flex-wrap">
|
<NewInventory i18n={i18n} grid={ship.grid} onAddInventory={addInventory} />
|
||||||
{#each Object.values(InventoryType) as inventory}
|
|
||||||
{#if newInventory === inventory}
|
|
||||||
<Button variant="primary">{localized(inventory)}</Button>
|
|
||||||
{:else}
|
|
||||||
<Button variant="secondary" onclick={() => newInventory = inventory}>{localized(inventory)}</Button>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
<Button variant="secondary" onclick={() => addInventory()}>{localized("addInventory")}</Button>
|
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
</Card.Root>
|
</Card.Root>
|
||||||
<Card.Root class="flex flex-col h-0 flex-grow">
|
<Card.Root class="flex flex-col h-60 flex-grow">
|
||||||
<Card.Header>
|
<Card.Header>
|
||||||
<Card.Title>{localized("inventories")} ({applyUnits(totalVolume, "l")})</Card.Title>
|
<Card.Title>{i18n.localize("inventories")} ({applyUnits(i18n, ship.getTotalVolume(inventoryMultiplier), "l")})</Card.Title>
|
||||||
</Card.Header>
|
</Card.Header>
|
||||||
<Card.Content class="overflow-hidden">
|
<Card.Content class="flex flex-col gap-3 overflow-hidden">
|
||||||
<Separator />
|
<Separator />
|
||||||
<div class="max-h-full overflow-y-auto">
|
<InventoryList i18n={i18n} bind:inventories={ship.inventories} grid={ship.grid} multiplier={inventoryMultiplier} />
|
||||||
{#each inventories as inventory, index}
|
|
||||||
<p class="p-1">
|
|
||||||
- {localized(inventory)} {localized("volume")}: {applyUnits(getInventoryVolume(inventory), "l")}
|
|
||||||
<Button variant="destructive" onclick={() => inventories.splice(index, 1)}>X</Button>
|
|
||||||
</p>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
</Card.Root>
|
</Card.Root>
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
|
|
Loading…
Reference in a new issue