got all subduxes in

docks66-json-schema
Yanick Champoux 2023-03-27 12:59:32 -04:00
parent 0e76cdd4d3
commit 8bb1955dff
8 changed files with 293 additions and 51 deletions

View File

@ -2,44 +2,26 @@ import { combineReducers, createSlice } from "@reduxjs/toolkit";
import { reqs } from "../reqs.js";
import * as weapons from "./weapons.js";
const firecons = createSlice({
name: "firecons",
initialState: {
stations: 0,
reqs,
},
reducers: {
setFirecons(state, action) {
const stations = action.payload;
state.stations = action.payload;
state.reqs = {
cost: 4 * stations,
mass: stations,
};
},
},
});
const adfc = createSlice({
name: "adfc",
initialState: {
rating: 0,
reqs,
},
reducers: {
setAdfc(state, action) {
const rating = action.payload;
state.rating = action.payload;
state.reqs = {
cost: 8 * rating,
mass: 2 * rating,
};
},
name: "adfc",
initialState: {
rating: 0,
reqs,
},
reducers: {
setAdfc(state, action) {
const rating = action.payload;
state.rating = action.payload;
state.reqs = {
cost: 8 * rating,
mass: 2 * rating,
};
},
},
});
export const reducer = combineReducers({
adfc: adfc.reducer,
firecons: firecons.reducer,
weapons: weapons.reducer,
adfc: adfc.reducer,
firecons: firecons.reducer,
weapons: weapons.reducer,
});

View File

@ -36,4 +36,15 @@ test("kicking the tires", () => {
cost: 0,
},
});
store.dispatch.setNbrArmorLayers(1);
store.dispatch.setArmorRating(1, 3);
expect(store.getState().structure.armor).toEqual({
layers: [3],
reqs: {
cost: 6,
mass: 6,
},
});
});

View File

@ -13,27 +13,48 @@ import { calcStreamliningReqs } from "./ship/structure/rules";
import { cargoDux } from "./ship/structure/cargo";
import { hullDux } from "./ship/structure/hull";
import { screensDux, screensReqsReaction } from "./ship/structure/screens";
import { armorDux } from "./ship/structure/armor";
import { fireconsDux } from "./ship/weaponry/firecons";
import { adfcDux } from "./ship/weaponry/adfc";
import { weaponsDux } from "./ship/weaponry/weapons";
process.env.UPDEEP_MODE = "dangerously_never_freeze";
const structure = new Updux({
initialState: {},
subduxes: {
streamlining,
cargo: cargoDux,
hull: hullDux,
screens: screensDux,
armor: armorDux,
},
});
const propulsion = new Updux({
initialState: {},
subduxes: {
ftl,
drive,
},
});
const weaponry = new Updux({
initialState: {},
subduxes: {
adfc: adfcDux,
firecons: fireconsDux,
weapons: weaponsDux,
},
});
const shipDux = new Updux({
subduxes: {
identification,
structure: new Updux({
initialState: {},
subduxes: {
streamlining,
cargo: cargoDux,
hull: hullDux,
screens: screensDux,
},
}),
propulsion: new Updux({
initialState: {},
subduxes: {
ftl,
drive,
},
}),
structure,
propulsion,
carrier: carrierDux,
weaponry,
},
});

View File

@ -0,0 +1,52 @@
import { reqs, type Reqs } from "$lib/shipDux/reqs";
import Updux, { createPayloadAction } from "updux";
import u from "@yanick/updeep-remeda";
import { createSelector } from "reselect";
import prepare from "immer";
type Layer = number;
const initialState = {
reqs,
layers: [] as Layer[],
};
const setNbrArmorLayers = createPayloadAction<number>("setNbrArmorLayers");
const setArmorRating = createPayloadAction(
"setArmorRating",
(id: number, rating: number) => ({ index: id - 1, rating })
);
export const armorDux = new Updux({
initialState,
actions: { setNbrArmorLayers, setArmorRating },
});
armorDux.addMutation(setArmorRating, ({ index, rating }) =>
prepare((state) => {
state.layers[index] = rating;
state.reqs = calcArmorReqs(state.layers);
})
);
armorDux.addMutation(setNbrArmorLayers, (nbrLayers) =>
prepare((state) => {
while (state.layers.length > nbrLayers) {
state.layers.pop();
}
while (state.layers.length < nbrLayers) {
state.layers.push(0);
}
state.reqs = calcArmorReqs(state.layers);
})
);
function calcArmorReqs(layers: Layer[]): Reqs {
const mass = 2 * layers.reduce((a, b) => a + b, 0);
const cost = 2 * layers.map((v, k) => v * (k + 1)).reduce((a, b) => a + b, 0);
return {
mass,
cost,
};
}

View File

@ -0,0 +1,20 @@
import { reqs } from "$lib/shipDux/reqs";
import Updux, { createPayloadAction } from "updux";
import u from "@yanick/updeep-remeda";
export const adfcDux = new Updux({
initialState: {
rating: 0,
reqs,
},
actions: {
setADFC: (rating: number) => rating,
},
});
adfcDux.addMutation(adfcDux.actions.setADFC, (rating) =>
u({
rating,
reqs: { cost: 8 * rating, mass: 2 * rating },
})
);

View File

@ -0,0 +1,20 @@
import { reqs } from "$lib/shipDux/reqs";
import Updux, { createPayloadAction } from "updux";
import u from "@yanick/updeep-remeda";
export const fireconsDux = new Updux({
initialState: {
stations: 0,
reqs,
},
actions: {
setFirecons: (stations: number) => stations,
},
});
fireconsDux.addMutation(fireconsDux.actions.setFirecons, (stations) =>
u({
stations,
reqs: { cost: 4 * stations, mass: stations },
})
);

View File

@ -0,0 +1,90 @@
import type { Reqs } from "$lib/shipDux/reqs";
export const weaponTypes = [
{
name: "beam",
type: "beam",
reqs: beamReqs,
initial: {
weaponClass: 1,
},
},
{
name: "submunition pack",
type: "submunition",
reqs: { mass: 1, cost: 3 },
initial: { arc: "F" },
},
{
name: "point defence system",
type: "pds",
reqs: { mass: 1, cost: 3 },
initial: {},
},
{
name: "scattergun",
type: "scattergun",
reqs: { mass: 1, cost: 4 },
initial: {},
},
{
name: "needle weapon",
type: "needle",
reqs: { mass: 2, cost: 6 },
initial: { arc: "F" },
},
];
export function weaponReqs(weapon): Reqs {
const { reqs } = weaponTypes.find((wt) => wt.type === weapon.type) || {};
if (!reqs) return {};
if (typeof reqs === "function") return reqs(weapon);
return reqs;
}
const isBroadside = (arcs) => {
if (arcs.length !== 4) return false;
// that'd be A or F
return !arcs.some((a) => a.length === 1);
};
function beamReqs({ weaponClass, arcs }) {
let mass;
if (weaponClass === 1) {
mass = 1;
}
if (weaponClass === 2) {
mass = 2 + (arcs.length > 3 ? 1 : 0);
}
if (weaponClass == 3) {
mass = 4;
if (isBroadside(arcs)) {
mass += 2;
} else {
mass += arcs.length - 1;
}
}
if (weaponClass == 4) {
mass = 8;
if (isBroadside(arcs)) {
mass += 4;
} else {
mass += 2 * (arcs.length - 1);
}
}
return {
mass,
cost: 3 * mass,
};
}

View File

@ -0,0 +1,46 @@
import type { Reqs } from "$lib/shipDux/reqs";
import Updux from "updux";
import u from "@yanick/updeep-remeda";
import * as R from "remeda";
import { weaponReqs } from "./rules";
import { nanoid } from "@reduxjs/toolkit";
type Weapon = {
weaponClass: string;
arcs?: unknown[];
type: string;
};
type IndexedWeapon = { id: string; reqs: Reqs; specs: Weapon };
export const weaponsDux = new Updux({
initialState: [] as IndexedWeapon[],
actions: {
removeWeapon: (id: string) => id,
setWeapon: (id: string, specs: Weapon) => ({ id, specs }),
addWeapon: (specs: Weapon) => specs,
},
});
weaponsDux.addMutation(weaponsDux.actions.removeWeapon, (id) =>
R.reject(u.matches({ id }))
);
weaponsDux.addMutation(
weaponsDux.actions.setWeapon,
({ id, specs }) =>
(state) => {
const weapon = state.find(u.matches({ id }));
if (!weapon) return;
weapon.specs = specs;
weapon.reqs = weaponReqs(specs);
}
);
weaponsDux.addMutation(weaponsDux.actions.addWeapon, (specs) => (state) => {
state.push({
id: nanoid(),
specs,
reqs: weaponReqs(specs),
});
});