streamlining, store and edit

docks66-json-schema
Yanick Champoux 2023-03-24 11:01:04 -04:00
parent 19293501cb
commit 074249d566
12 changed files with 154 additions and 70 deletions

View File

@ -1,5 +1,5 @@
<Hst.Story>
<ShipEdit {ship} />
<ShipEdit {...ship} />
</Hst.Story>
<script>
@ -14,8 +14,5 @@
let ship = api.getState();
api.subscribe(() => {
console.log("update!");
ship = api.getState();
});
api.subscribe(() => (ship = api.getState()));
</script>

View File

@ -1,14 +1,18 @@
<main>
<Identification {...ship.identification} />
<Propulsion {...ship.propulsion} />
<Identification {...identification} />
<Propulsion {...propulsion} />
<Structure {...structure} />
</main>
<script>
import Identification from "./ShipEdit/Identification.svelte";
import Propulsion from "./ShipEdit/Propulsion.svelte";
import shipDux from "$lib/store/ship";
import Structure from "./ShipEdit/Structure.svelte";
export let ship = shipDux.initial;
export let identification = {};
export let propulsion = {};
export let structure = {};
</script>
<style>

View File

@ -0,0 +1,10 @@
<Section label="structure">
<Streamlining {...streamlining} />
</Section>
<script lang="ts">
import Section from "$lib/components/Section.svelte";
import Streamlining from "./Structure/Streamlining.svelte";
export let streamlining = {};
</script>

View File

@ -18,17 +18,17 @@
</ShipItem>
<script>
import ShipItem from "$lib/components/ShipItem/index.svelte";
import Field from "$lib/components/Field/index.svelte";
import ShipItem from "$lib/components/ShipItem.svelte";
import Field from "$lib/components/Field.svelte";
import { getContext } from "svelte";
export let type = "none";
export let reqs = {};
export let {dispatch, shipMass} = getContext("ship");
export let api = getContext("api");
$: dispatch.setStreamlining({type, shipMass: $shipMass});
$: api?.dispatch?.setStreamlining?.(type);
</script>
<style>

View File

@ -1,23 +1,32 @@
import { test, expect } from "vitest";
import ship from "./ship";
test("misc", () => {
const store = ship.createStore();
store.dispatch.setFtlType("standard");
test("kicking the tires", () => {
const store = ship.createStore();
console.log(store.getState());
console.log(store.getState.getStreamlining());
store.dispatch.setFtlType("standard");
expect(store.getState().propulsion.ftl.reqs.mass).toEqual(1);
expect(store.getState().identification.reqs.usedMass).toEqual(1);
expect(store.getState().propulsion.ftl.reqs.mass).toEqual(1);
expect(store.getState().identification.reqs.usedMass).toEqual(1);
store.dispatch.setDrive({ rating: 3, advanced: true });
store.dispatch.setDrive({ rating: 3, advanced: true });
expect(store.getState().propulsion.drive.reqs).toEqual({ mass: 2, cost: 6 });
expect(store.getState().propulsion.drive.reqs).toEqual({ mass: 2, cost: 6 });
store.dispatch.setNbrCarrierBays(1);
expect(store.getState().carrier.nbrBays).toEqual(1);
store.dispatch.setNbrCarrierBays(2);
expect(store.getState().carrier.nbrBays).toEqual(2);
store.dispatch.setNbrCarrierBays(1);
expect(store.getState().carrier.nbrBays).toEqual(1);
store.dispatch.setNbrCarrierBays(2);
expect(store.getState().carrier.nbrBays).toEqual(2);
store.dispatch.setSquadronType(2, "fast");
store.dispatch.setSquadronType(2, "fast");
expect(store.getState().carrier.squadrons[1]).toHaveProperty("type", "fast");
expect(store.getState().carrier.squadrons[1]).toHaveProperty("type", "fast");
expect(store.getState.isCarrier()).toBe(true);
store.dispatch.setStreamlining("partial");
expect(store.getState.getStreamlining()).toBe("partial");
expect(store.selectors.getStreamlining(store.getState())).toBe("partial");
});

View File

@ -7,58 +7,78 @@ import ftl, { calcFtlReqs } from "./ship/propulsion/ftl";
import drive from "./ship/propulsion/drive";
import { calcDriveReqs } from "$lib/shipDux/engine";
import { carrierDux } from "./ship/carrier";
import { streamliningDux as streamlining } from "./ship/structure/streamlining";
import { calcStreamliningReqs } from "./ship/structure/rules";
const shipDux = new Updux({
subduxes: {
identification,
propulsion: new Updux({
initial: {},
subduxes: {
ftl,
drive,
},
}),
carrier: carrierDux,
},
subduxes: {
identification,
structure: new Updux({
initialState: {},
subduxes: {
streamlining,
},
}),
propulsion: new Updux({
initialState: {},
subduxes: {
ftl,
drive,
},
}),
carrier: carrierDux,
},
});
shipDux.addReaction((api) =>
createSelector(
api.selectors.getFtlType,
api.selectors.getShipMass,
(type, mass) => api.dispatch.setFtlReqs(calcFtlReqs(type, mass))
)
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 cost = 0;
let mass = 0;
let subsystems = R.values(R.omit(state, ["identification"]));
let subsystems = R.values(R.omit(state, ["identification"]));
while (subsystems.length > 0) {
const subsystem = subsystems.shift();
if (typeof subsystem !== "object") continue;
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));
if (subsystem.reqs) {
cost += subsystem.reqs.cost;
mass += subsystem.reqs.mass;
}
api.dispatch.setShipReqs({ cost, usedMass: mass });
subsystems.push(...Object.values(subsystem));
}
api.dispatch.setShipReqs({ cost, usedMass: mass });
});
shipDux.addReaction((api) =>
createSelector(
api.selectors.getShipMass,
(state) => state.propulsion.drive.rating,
(state) => state.propulsion.drive.advanced,
(mass, rating, advanced) =>
api.dispatch.setDriveReqs(calcDriveReqs(mass, rating, advanced))
)
createSelector(
api.selectors.getShipMass,
(state) => state.propulsion.drive.rating,
(state) => state.propulsion.drive.advanced,
(mass, rating, advanced) =>
api.dispatch.setDriveReqs(calcDriveReqs(mass, rating, advanced))
)
);
shipDux.addReaction((api) =>
createSelector(
// (state) => state,
api.selectors.getShipMass,
api.selectors.getStreamlining,
(mass, type) => {
console.log("AH!", mass, type);
api.dispatch.setStreamliningReqs(calcStreamliningReqs(type, mass));
}
)
);
export default shipDux;

View File

@ -7,7 +7,7 @@ type Squadron = {
reqs: Reqs;
};
const initial = {
const initialState = {
nbrBays: 0,
squadrons: [] as Squadron[],
reqs,
@ -30,7 +30,7 @@ const setSquadronType = createPayloadAction(
);
export const carrierDux = new Updux({
initial,
initialState,
actions: { setNbrCarrierBays, setSquadronType },
});
@ -93,7 +93,7 @@ function squadronReqs(type: string) {
/*
export const { actions, reducer } = createSlice({
name: "carrier",
initialState,
initialStateState,
reducers: {
setCarrierBays: (state, action: PayloadAction<number>) => {
state.bays = action.payload;

View File

@ -1,7 +1,9 @@
import Updux, { createAction, withPayload } from "updux";
import u from "@yanick/updeep-remeda";
import * as R from "remeda";
import { carrierDux } from "./carrier";
const initial = {
const initialState = {
shipType: "",
shipClass: "",
isCarrier: false,
@ -17,7 +19,7 @@ const updateIdentification = createAction("updateIdentification");
const setShipReqs = createAction("setShipReqs", withPayload());
export const dux = new Updux({
initial,
initialState,
actions: {
setShipClass,
updateIdentification,
@ -25,6 +27,7 @@ export const dux = new Updux({
},
selectors: {
getShipMass: (state) => state.reqs.mass,
isCarrier: ({ isCarrier }) => isCarrier,
},
});
@ -32,4 +35,10 @@ dux.addMutation(setShipClass, (shipClass) => u({ shipClass }));
dux.addMutation(updateIdentification, (update) => u(update));
dux.addMutation(setShipReqs, (reqs) => u({ reqs }));
dux.addMutation(carrierDux.actions.setNbrCarrierBays, (nbrBays) =>
u({
isCarrier: nbrBays > 0,
})
);
export default dux;

View File

@ -7,7 +7,7 @@ type DriveProps = {
advanced: boolean;
};
const initial: DriveProps & { reqs: Reqs } = {
const initialState: DriveProps & { reqs: Reqs } = {
rating: 0,
advanced: false,
reqs,
@ -17,7 +17,7 @@ const setDrive = createPayloadAction<DriveProps>("setDrive");
const setDriveReqs = createPayloadAction<Reqs>("setDriveReqs");
const dux = new Updux({
initial,
initialState,
actions: { setDrive, setDriveReqs },
});

View File

@ -7,7 +7,7 @@ export const ftlTypes = ["none", "standard", "advanced"] as const;
type FtlType = typeof ftlTypes[number];
export const initial = {
export const initialState = {
reqs,
type: "none" as FtlType,
};
@ -16,7 +16,7 @@ const setFtlType = createAction("setFtlType", withPayload<FtlType>());
const setFtlReqs = createAction("setFtlReqs", withPayload<Reqs>());
const dux = new Updux({
initial,
initialState,
actions: { setFtlType, setFtlReqs },
selectors: {
getFtlType: R.prop<any, any>("type"),

View File

@ -0,0 +1,9 @@
export type Streamlining = "none" | "partial" | "full";
export function calcStreamliningReqs(type: Streamlining, shipMass: number) {
const mass = Math.ceil(
(shipMass * (type === "none" ? 0 : type === "partial" ? 5 : 10)) / 100
);
return { mass, cost: 2 * mass };
}

View File

@ -0,0 +1,26 @@
import { reqs } from "$lib/shipDux/reqs";
import Updux, { createPayloadAction } from "updux";
import type { Streamlining } from "./rules";
import u from "@yanick/updeep-remeda";
const initialState = {
type: "none" as Streamlining,
reqs,
};
const setStreamlining = createPayloadAction<Streamlining>("setStreamlining");
const setStreamliningReqs = createPayloadAction("setStreamliningReqs");
export const streamliningDux = new Updux({
initialState,
actions: { setStreamlining, setStreamliningReqs },
selectors: {
getStreamlining: (state) => {
return state?.type;
},
},
});
streamliningDux.addMutation(setStreamlining, (type) => u({ type }));
streamliningDux.addMutation(setStreamliningReqs, (reqs) => u({ reqs }));