<svelte:options runes={true} /> <script lang="ts"> import * as Card from "$lib/components/ui/card"; import {Button} from "$lib/components/ui/button"; import { 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"; const STORAGE_VERSION = "2"; let i18n = $state(new Localization("en-GB")); let mounted = $state(false); let ship = $state(new Ship(Grid.Small)); $effect(() => { ship.thrusters; if (mounted) { localStorage.setItem("ship", JSON.stringify(ship.save())); } }) let inventoryMultiplier: number = $state(3); $effect(() => { if (mounted) { localStorage.setItem("inventoryMultiplier", inventoryMultiplier); } }) let gravity: number = $state(1); $effect(() => { if (mounted) { localStorage.setItem("gravity", gravity); } }) let material: CargoMaterial = $state(CargoMaterial.Ore); $effect(() => { if (mounted) { localStorage.setItem("density", material.save()); } }) let atmosphericDensity: number = $state(1); $effect(() => { if (mounted) { localStorage.setItem("atmosphericDensity", atmosphericDensity); } }) let maxWeight: number = $derived(ship.getTotalMaxThrust() / (gravity * 9.81)) let maxVehicleWeight: number = $derived(maxWeight - ship.getTotalVolume(inventoryMultiplier) * material.density) $inspect(maxVehicleWeight); $inspect(`${maxWeight} - ${ship.getTotalVolume(inventoryMultiplier)} * ${material.density} = ${maxVehicleWeight}`) function addInventory(newInventory: Inventory) { ship.addInventory(newInventory); } function addThruster(newThruster: Thruster) { ship.addThruster(newThruster); } onMount(() => { if (navigator) { i18n.language = navigator.language; } let ret = getFromLocalStorage("version"); if (ret.result) { console.log(ret); if (ret.value !== STORAGE_VERSION) { localStorage.clear(); localStorage.setItem("version", STORAGE_VERSION); } } else { localStorage.clear(); localStorage.setItem("version", STORAGE_VERSION); } ret = getFromLocalStorage("ship"); if (ret.result) { ship.load(JSON.parse(ret.value)); } ret = getFromLocalStorage("gravity"); if (ret.result) { gravity = ret.value; } ret = getFromLocalStorage("density"); if (ret.result) { let parsed = ret.value; Object.values(CargoMaterial).forEach((cargoMaterial) => { if (cargoMaterial.name === parsed) { material = cargoMaterial } }) } ret = getFromLocalStorage("atmosphericDensity"); if (ret.result) { atmosphericDensity = ret.value; } ret = getFromLocalStorage("inventoryMultiplier"); if (ret.result) { inventoryMultiplier = ret.value; } mounted = true; }) </script> <svelte:head> <title>{i18n.localize("title")}</title> <meta name="robots" content="noindex nofollow" /> </svelte:head> <div class="gap-4 flex flex-row flex-wrap h-full"> <Card.Root class="flex-1"> <Card.Header> <Card.Title>{i18n.localize("title")}</Card.Title> </Card.Header> <Card.Content class="flex flex-col gap-3"> <Separator /> <Label for="gravity">{i18n.localize("gravity")}</Label> <Input type="number" step="0.01" id="gravity" bind:value={gravity}/> <Label for="atmosDensity">{i18n.localize("atmosDensity")}</Label> <Input type="number" step="0.01" id="atmosDensity" bind:value={atmosphericDensity}/> <Separator /> <Label for="gridSize">{i18n.localize("gridSize")}</Label> <div id="gridSize" class="flex gap-2"> {#each Object.values(Grid) as size} {#if ship.grid === size} <Button class="bg-primary">{i18n.localize(size)}</Button> {:else} <Button variant="secondary" onclick={() => ship.grid = size}>{i18n.localize(size)}</Button> {/if} {/each} </div> <Separator /> <Label for="density">{i18n.localize("density")}</Label> <div id="density" class="flex gap-2"> {#each Object.values(CargoMaterial) as value} {#if material === value} <Button class="bg-primary">{i18n.localize(value.name)}</Button> {:else} <Button variant="secondary" onclick={() => material = value}>{i18n.localize(value.name)}</Button> {/if} {/each} </div> <Separator /> <p>{i18n.localize("liftableVehcileWeight")}: {weightConversion(i18n, maxVehicleWeight)}</p> <p>{i18n.localize("liftableWeight")}: {weightConversion(i18n, maxWeight)}</p> </Card.Content> </Card.Root> <Card.Root class="flex-1 flex flex-col flex-grow"> <Card.Header> <Card.Title>{i18n.localize("thrusterSettings")}</Card.Title> </Card.Header> <Card.Content class="flex flex-col flex-grow gap-3"> <Separator /> <Card.Root> <Card.Content class="flex flex-col gap-3 pt-6"> <NewThruster i18n={i18n} onAddThruster={addThruster} /> </Card.Content> </Card.Root> <Card.Root class="flex flex-col h-60 flex-grow"> <Card.Header> <Card.Title>{i18n.localize("thrusters")} ({applyUnits(i18n, ship.getTotalThrust(atmosphericDensity), "N")})</Card.Title> </Card.Header> <Card.Content class="flex flex-col gap-3 overflow-hidden"> <Separator /> <ThrusterList i18n={i18n} bind:thrusters={ship.thrusters} grid={ship.grid} atmosphere={atmosphericDensity}/> </Card.Content> </Card.Root> </Card.Content> </Card.Root> <Card.Root class="flex-1 flex flex-col flex-grow"> <Card.Header> <Card.Title>{i18n.localize("inventorySettings")}</Card.Title> </Card.Header> <Card.Content class="flex flex-col flex-grow gap-3"> <Separator /> <Label for="inventorySize">{i18n.localize("inventory")} {i18n.localize("multiplier")}</Label> <Input id="inventorySize" type="number" bind:value={inventoryMultiplier}/> <Card.Root> <Card.Content class="pt-6 flex flex-col gap-3"> <NewInventory i18n={i18n} grid={ship.grid} onAddInventory={addInventory} /> </Card.Content> </Card.Root> <Card.Root class="flex flex-col h-60 flex-grow"> <Card.Header> <Card.Title>{i18n.localize("inventories")} ({applyUnits(i18n, ship.getTotalVolume(inventoryMultiplier), "l")})</Card.Title> </Card.Header> <Card.Content class="flex flex-col gap-3 overflow-hidden"> <Separator /> <InventoryList i18n={i18n} bind:inventories={ship.inventories} grid={ship.grid} multiplier={inventoryMultiplier} /> </Card.Content> </Card.Root> </Card.Content> </Card.Root> </div>