ShipEdit with propulsion
This commit is contained in:
parent
cdb7e8ee35
commit
a415278b6a
@ -116,7 +116,7 @@
|
||||
border: 1px solid var(--indigo-dye);
|
||||
}
|
||||
|
||||
input:not([type="checkbox"]) {
|
||||
input:not([type="checkbox"]):not([type="radio"]) {
|
||||
border: 0px;
|
||||
border-bottom: 1px solid var(--indigo-dye);
|
||||
border-radius: 0px;
|
||||
|
@ -1,13 +1,14 @@
|
||||
<main>
|
||||
<Identification {...ship.identification} />
|
||||
<Propulsion {...ship.propulsion} />
|
||||
</main>
|
||||
|
||||
<script>
|
||||
import Identification from "./ShipEdit/Identification.svelte";
|
||||
import Propulsion from "./ShipEdit/Propulsion.svelte";
|
||||
import shipDux from "$lib/store/ship";
|
||||
|
||||
export let ship = {
|
||||
identification: {},
|
||||
};
|
||||
export let ship = shipDux.initial;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
@ -25,7 +25,7 @@
|
||||
export let rating = 0;
|
||||
export let api = getContext("api");
|
||||
|
||||
$: api?.dispatch?.setEngine({ rating, advanced });
|
||||
$: api?.dispatch?.setEngine?.({ rating, advanced });
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<ShipItem {...reqs}>
|
||||
<Field label="FTL drive">
|
||||
{#each types as t (t)}
|
||||
{#each ftlTypes as t (t)}
|
||||
<label
|
||||
><input type="radio" bind:group={type} value={t} />
|
||||
{t}
|
||||
@ -15,13 +15,13 @@
|
||||
import ShipItem from "$lib/components/ShipItem.svelte";
|
||||
import Field from "$lib/components/Field.svelte";
|
||||
|
||||
import { ftlTypes } from "$lib/store/ship/propulsion/ftl";
|
||||
|
||||
export let type = "none";
|
||||
export let reqs = { mass: 0, cost: 0 };
|
||||
export let api = getContext("api");
|
||||
|
||||
const types = ["none", "standard", "advanced"];
|
||||
|
||||
$: api?.dispatch.setFtl(type);
|
||||
$: api?.dispatch.setFtlType?.(type);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
@ -5,14 +5,6 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
|
||||
import { reqs, Reqs } from "../reqs.js";
|
||||
|
||||
export const ftlTypes = ["none", "standard", "advanced"] as const;
|
||||
type FtlType = typeof ftlTypes[number];
|
||||
|
||||
export const initialState = {
|
||||
reqs,
|
||||
type: "none" as FtlType,
|
||||
};
|
||||
|
||||
const ftl = createSlice({
|
||||
name: "ftl",
|
||||
initialState,
|
||||
@ -26,22 +18,4 @@ const ftl = createSlice({
|
||||
},
|
||||
});
|
||||
|
||||
export function calcFtlReqs(type: FtlType, shipMass: number): Reqs {
|
||||
if (type === "none") return { cost: 0, mass: 0 };
|
||||
|
||||
const mass = Math.ceil(shipMass / 10);
|
||||
|
||||
return {
|
||||
mass,
|
||||
cost: mass * (type === "advanced" ? 3 : 2),
|
||||
};
|
||||
}
|
||||
|
||||
export const { actions, reducer } = ftl;
|
||||
|
||||
// needs to be at the top level
|
||||
export const ftlReqsReaction = (store) =>
|
||||
createSelector(
|
||||
[(ship) => ship.propulsion.ftl.type, (ship) => ship.reqs.mass],
|
||||
(type, shipMass) => store.dispatch.setFtlReqs(calcFtlReqs(type, shipMass))
|
||||
);
|
||||
|
10
src/lib/store/ship.test.ts
Normal file
10
src/lib/store/ship.test.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { test, expect } from "vitest";
|
||||
import ship from "./ship";
|
||||
|
||||
test("ftlReqs reaction", () => {
|
||||
const store = ship.createStore();
|
||||
store.dispatch.setFtlType("standard");
|
||||
|
||||
expect(store.getState().propulsion.ftl.reqs.mass).toEqual(1);
|
||||
expect(store.getState().identification.reqs.usedMass).toEqual(1);
|
||||
});
|
@ -1,11 +1,48 @@
|
||||
import { createSelector } from "@reduxjs/toolkit";
|
||||
import Updux from "updux";
|
||||
import * as R from "remeda";
|
||||
|
||||
import identification from "./ship/identification";
|
||||
import ftl, { calcFtlReqs } from "./ship/propulsion/ftl";
|
||||
|
||||
const shipDux = new Updux({
|
||||
subduxes: {
|
||||
identification,
|
||||
propulsion: new Updux({
|
||||
subduxes: {
|
||||
ftl,
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
shipDux.addReaction((api) =>
|
||||
createSelector(
|
||||
api.selectors.getFtlType,
|
||||
api.selectors.getShipMass,
|
||||
(type, mass) => api.dispatch.setFtlReqs(calcFtlReqs(type, mass))
|
||||
)
|
||||
);
|
||||
|
||||
shipDux.addReaction((api) => (state) => {
|
||||
let cost = 0;
|
||||
let mass = 0;
|
||||
|
||||
let subsystems = R.values(R.omit(state, ["identification"]));
|
||||
|
||||
while (subsystems.length > 0) {
|
||||
const subsystem = subsystems.shift();
|
||||
if (typeof subsystem !== "object") continue;
|
||||
|
||||
if (subsystem.reqs) {
|
||||
cost += subsystem.reqs.cost;
|
||||
mass += subsystem.reqs.mass;
|
||||
}
|
||||
|
||||
subsystems.push(...Object.values(subsystem));
|
||||
}
|
||||
|
||||
api.dispatch.setShipReqs({ cost, usedMass: mass });
|
||||
});
|
||||
|
||||
export default shipDux;
|
||||
|
@ -14,16 +14,22 @@ const initial = {
|
||||
|
||||
const setShipClass = createAction("setShipClass", withPayload<string>());
|
||||
const updateIdentification = createAction("updateIdentification");
|
||||
const setShipReqs = createAction("setShipReqs", withPayload());
|
||||
|
||||
export const dux = new Updux({
|
||||
initial,
|
||||
actions: {
|
||||
setShipClass,
|
||||
updateIdentification,
|
||||
setShipReqs,
|
||||
},
|
||||
selectors: {
|
||||
getShipMass: (state) => state.reqs.mass,
|
||||
},
|
||||
});
|
||||
|
||||
dux.addMutation(setShipClass, (shipClass) => u({ shipClass }));
|
||||
dux.addMutation(updateIdentification, (update) => u(update));
|
||||
dux.addMutation(setShipReqs, (reqs) => u({ reqs }));
|
||||
|
||||
export default dux;
|
||||
|
40
src/lib/store/ship/propulsion/ftl.ts
Normal file
40
src/lib/store/ship/propulsion/ftl.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { reqs, type Reqs } from "$lib/shipDux/reqs";
|
||||
import Updux, { createAction, withPayload } from "updux";
|
||||
import u from "@yanick/updeep-remeda";
|
||||
import * as R from "remeda";
|
||||
|
||||
export const ftlTypes = ["none", "standard", "advanced"] as const;
|
||||
|
||||
type FtlType = typeof ftlTypes[number];
|
||||
|
||||
export const initial = {
|
||||
reqs,
|
||||
type: "none" as FtlType,
|
||||
};
|
||||
|
||||
const setFtlType = createAction("setFtlType", withPayload<FtlType>());
|
||||
const setFtlReqs = createAction("setFtlReqs", withPayload<Reqs>());
|
||||
|
||||
const dux = new Updux({
|
||||
initial,
|
||||
actions: { setFtlType, setFtlReqs },
|
||||
selectors: {
|
||||
getFtlType: R.prop<any, any>("type"),
|
||||
},
|
||||
});
|
||||
|
||||
dux.addMutation(setFtlType, (type) => u({ type }));
|
||||
dux.addMutation(setFtlReqs, (reqs) => u({ reqs }));
|
||||
|
||||
export default dux;
|
||||
|
||||
export function calcFtlReqs(type: FtlType, shipMass: number): Reqs {
|
||||
if (type === "none") return { cost: 0, mass: 0 };
|
||||
|
||||
const mass = Math.ceil(shipMass / 10);
|
||||
|
||||
return {
|
||||
mass,
|
||||
cost: mass * (type === "advanced" ? 3 : 2),
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user