Merge branch 'identification' into version-2
This commit is contained in:
commit
0a0b78336d
@ -27,6 +27,7 @@ module.exports = {
|
||||
$app: path.resolve("./fake/app"),
|
||||
"\\$lib": path.resolve(__dirname, "../src/lib/"),
|
||||
$lib: path.resolve(__dirname, "../src/lib/"),
|
||||
"\\$app/env": path.resolve(__dirname, "../fake/app/env.js"),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
1
fake/app/env.js
Normal file
1
fake/app/env.js
Normal file
@ -0,0 +1 @@
|
||||
export const browser = true;
|
@ -35,14 +35,13 @@
|
||||
"@storybook/addon-svelte-csf": "^1.1.0",
|
||||
"@storybook/svelte": "^6.4.19",
|
||||
"@sveltejs/adapter-node": "^1.0.0-next.0",
|
||||
"@yanick/updeep": "link:/home/yanick/work/javascript/updeep",
|
||||
"lodash": "^4.17.21",
|
||||
"redux": "^4.1.2",
|
||||
"reselect": "^4.1.5",
|
||||
"rollup-plugin-analyzer": "^4.0.0",
|
||||
"svelte-knobby": "^0.3.4",
|
||||
"ts-action": "^11.0.0",
|
||||
"updux": "link:/home/yanick/work/javascript/updux/",
|
||||
"updux": "link:/home/yanick/work/javascript/updux-js/",
|
||||
"webpack": "5"
|
||||
},
|
||||
"prettier": {
|
||||
|
140
src/dux/index.js
140
src/dux/index.js
@ -5,15 +5,15 @@ import { createSelector } from "reselect";
|
||||
|
||||
import ftl from "./ftl";
|
||||
import engine, { calc_drive_reqs } from "./engine";
|
||||
import weaponry from './weaponry';
|
||||
import weaponry from "./weaponry";
|
||||
import { calc_ftl_reqs } from "./ftl/rules";
|
||||
import { calc_ship_req } from "./utils";
|
||||
import { candidate_ship_types } from './ship_types';
|
||||
import structure from './structure';
|
||||
import cargo from './cargo';
|
||||
import streamlining from './streamlining';
|
||||
import carrier from './carrier';
|
||||
import { ceil } from './utils';
|
||||
import { candidate_ship_types } from "./ship_types";
|
||||
import structure from "./structure";
|
||||
import cargo from "./cargo";
|
||||
import streamlining from "./streamlining";
|
||||
import carrier from "./carrier";
|
||||
import { ceil } from "./utils";
|
||||
|
||||
const set_ship_mass = action("set_ship_mass", payload());
|
||||
const set_name = action("set_name", payload());
|
||||
@ -21,31 +21,29 @@ const set_name = action("set_name", payload());
|
||||
const set_ship_reqs = action("set_ship_reqs", payload());
|
||||
const set_hull = action("set_hull", payload());
|
||||
|
||||
const set_ship_type = action('set_ship_type',payload());
|
||||
const set_ship_type = action("set_ship_type", payload());
|
||||
|
||||
const reset = action('reset' );
|
||||
const reset = action("reset");
|
||||
|
||||
const initial = {
|
||||
general: {
|
||||
ship_class: "",
|
||||
name: "",
|
||||
ship_type: "",
|
||||
mass: 10,
|
||||
used_mass: 0,
|
||||
cost: 10,
|
||||
},
|
||||
};
|
||||
|
||||
console.log(Updux);
|
||||
general: {
|
||||
ship_class: "",
|
||||
name: "",
|
||||
ship_type: "",
|
||||
mass: 10,
|
||||
used_mass: 0,
|
||||
cost: 10,
|
||||
},
|
||||
};
|
||||
|
||||
const dux = new Updux({
|
||||
subduxes: { ftl, engine, weaponry, structure, cargo, streamlining, carrier },
|
||||
initial
|
||||
initial,
|
||||
});
|
||||
|
||||
dux.addMutation( reset, () => () => initial );
|
||||
dux.addMutation(reset, () => () => initial);
|
||||
|
||||
dux.addMutation(set_hull, ({rating}) => (state) => {
|
||||
dux.addMutation(set_hull, ({ rating }) => (state) => {
|
||||
return u.updateIn("structure.hull", {
|
||||
cost: 2 * rating,
|
||||
rating,
|
||||
@ -55,8 +53,8 @@ dux.addMutation(set_hull, ({rating}) => (state) => {
|
||||
dux.addMutation(set_ship_mass, (mass) => u.updateIn("general", { mass }));
|
||||
dux.addMutation(set_name, (name) => u.updateIn("general", { name }));
|
||||
|
||||
dux.addMutation( action('set_ship_class',payload() ),
|
||||
ship_class => u.updateIn('general',{ship_class})
|
||||
dux.addMutation(action("set_ship_class", payload()), (ship_class) =>
|
||||
u.updateIn("general", { ship_class })
|
||||
);
|
||||
|
||||
dux.addMutation(set_ship_reqs, ({ cost, mass: used_mass }) =>
|
||||
@ -70,71 +68,73 @@ dux.addSubscription((store) =>
|
||||
|
||||
dux.addSubscription((store) =>
|
||||
createSelector(
|
||||
store => store.general.mass,
|
||||
store => store.streamlining.type,
|
||||
(ship_mass, streamlining ) => {
|
||||
const mass = ceil( ship_mass * (
|
||||
streamlining === 'none' ? 0
|
||||
: streamlining === 'partial' ? 5 : 10
|
||||
) / 100 );
|
||||
const cost = 2 * mass;
|
||||
(store) => store.general.mass,
|
||||
(store) => store.streamlining.type,
|
||||
(ship_mass, streamlining) => {
|
||||
const mass = ceil(
|
||||
(ship_mass *
|
||||
(streamlining === "none" ? 0 : streamlining === "partial" ? 5 : 10)) /
|
||||
100
|
||||
);
|
||||
const cost = 2 * mass;
|
||||
|
||||
store.dispatch( dux.actions.set_streamlining_cost_mass({cost,mass}) );
|
||||
}
|
||||
store.dispatch(dux.actions.set_streamlining_cost_mass({ cost, mass }));
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
dux.addSubscription((store) =>
|
||||
createSelector(
|
||||
store => store.general.mass,
|
||||
store => store.general.ship_type,
|
||||
store => store.carrier.bays,
|
||||
(mass,type,bays) => {
|
||||
console.log({bays});
|
||||
const candidates = candidate_ship_types(mass,bays > 0);
|
||||
createSelector(
|
||||
(store) => store.general.mass,
|
||||
(store) => store.general.ship_type,
|
||||
(store) => store.carrier.bays,
|
||||
(mass, type, bays) => {
|
||||
console.log({ bays });
|
||||
const candidates = candidate_ship_types(mass, bays > 0);
|
||||
|
||||
console.log({candidates});
|
||||
if( candidates.length === 0 ) return;
|
||||
console.log({ candidates });
|
||||
if (candidates.length === 0) return;
|
||||
|
||||
if( candidates.find( ({name}) => name === type ) ) return;
|
||||
if (candidates.find(({ name }) => name === type)) return;
|
||||
|
||||
store.dispatch(
|
||||
store.actions.set_ship_type(
|
||||
candidates[0].name
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
)
|
||||
store.dispatch(store.actions.set_ship_type(candidates[0].name));
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
dux.addMutation(set_ship_type, type => u.updateIn('general.ship_type',type) );
|
||||
dux.addMutation(set_ship_type, (type) => u.updateIn("general.ship_type", type));
|
||||
|
||||
dux.addSubscription((store) =>
|
||||
createSelector(
|
||||
[(ship) => ship.general.mass, (ship) => ship.ftl.type],
|
||||
(ship_mass, type) =>
|
||||
store.dispatch(ftl.actions.set_ftl_reqs(calc_ftl_reqs(type,ship_mass)))
|
||||
store.dispatch(ftl.actions.set_ftl_reqs(calc_ftl_reqs(type, ship_mass)))
|
||||
)
|
||||
);
|
||||
|
||||
dux.addSubscription( store => createSelector(
|
||||
ship => ship.general.mass,
|
||||
ship => ship.structure.screens.standard,
|
||||
ship => ship.structure.screens.advanced,
|
||||
(mass,standard,advanced) => {
|
||||
console.log({
|
||||
mass, standard, advanced
|
||||
})
|
||||
const standard_mass = standard * Math.max(3,ceil( 0.05 * mass ));
|
||||
const advanced_mass = advanced * Math.max(4,ceil( 0.075 * mass ));
|
||||
dux.addSubscription((store) =>
|
||||
createSelector(
|
||||
(ship) => ship.general.mass,
|
||||
(ship) => ship.structure.screens.standard,
|
||||
(ship) => ship.structure.screens.advanced,
|
||||
(mass, standard, advanced) => {
|
||||
console.log({
|
||||
mass,
|
||||
standard,
|
||||
advanced,
|
||||
});
|
||||
const standard_mass = standard * Math.max(3, ceil(0.05 * mass));
|
||||
const advanced_mass = advanced * Math.max(4, ceil(0.075 * mass));
|
||||
|
||||
store.dispatch( dux.actions.set_screens_reqs({
|
||||
mass: standard_mass + advanced_mass,
|
||||
cost: 3 * standard_mass + 4 * advanced_mass
|
||||
}));
|
||||
store.dispatch(
|
||||
dux.actions.set_screens_reqs({
|
||||
mass: standard_mass + advanced_mass,
|
||||
cost: 3 * standard_mass + 4 * advanced_mass,
|
||||
})
|
||||
);
|
||||
}
|
||||
));
|
||||
)
|
||||
);
|
||||
|
||||
dux.addSubscription((store) =>
|
||||
createSelector(
|
||||
|
@ -3,7 +3,7 @@
|
||||
<label>{label}</label>
|
||||
{/if}
|
||||
<slot>
|
||||
<input type="text" {placeholder} {value} on:change />
|
||||
<input type="text" {placeholder} bind:value on:change />
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
|
@ -0,0 +1,22 @@
|
||||
<Meta title="Identification" component={Identification} argTypes={{}} />
|
||||
|
||||
<Story name="Primary" args={{}} />
|
||||
|
||||
<Template let:args>
|
||||
<div style="width: 50em">
|
||||
<Identification {...args} />
|
||||
</div>
|
||||
</Template>
|
||||
|
||||
<script>
|
||||
import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
|
||||
import { setContext } from "svelte";
|
||||
|
||||
import Identification from "./index.svelte";
|
||||
|
||||
setContext("ship", {
|
||||
dispatch: (type, detail) => action(type)(detail),
|
||||
});
|
||||
</script>
|
40
src/lib/components/ShipEdit/Identification/index.svelte
Normal file
40
src/lib/components/ShipEdit/Identification/index.svelte
Normal file
@ -0,0 +1,40 @@
|
||||
<div>
|
||||
<Field label="ship class" bind:value={shipClass} />
|
||||
<Field label="ship type">
|
||||
<select bind:value={shipType}>
|
||||
{#each shipTypes as name (name)}
|
||||
<option>{name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import { getContext } from "svelte";
|
||||
|
||||
import Field from "$lib/components/Field/index.svelte";
|
||||
import { candidateShipTypes } from "./shipTypes.js";
|
||||
|
||||
export let shipClass = "";
|
||||
export let shipType = "";
|
||||
export let mass = 10;
|
||||
export let isCarrier = false;
|
||||
|
||||
const ship = getContext("ship");
|
||||
|
||||
$: shipTypes = candidateShipTypes(mass, isCarrier).map(({ name }) => name);
|
||||
|
||||
$: if (shipTypes.length > 0 && !shipTypes.includes(shipType))
|
||||
shipType = shipTypes[0];
|
||||
|
||||
$: ship.dispatch.setShipType(shipType);
|
||||
$: ship.dispatch.setShipClass(shipClass);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div {
|
||||
display: flex;
|
||||
align-items: end;
|
||||
gap: 2em;
|
||||
}
|
||||
</style>
|
@ -20,7 +20,9 @@ const ship_types = [
|
||||
{ name: "Attack Carrier", mass: [150, 300], abbrev: "CVA", carrier: true },
|
||||
];
|
||||
|
||||
export function candidate_ship_types(mass = 0, carrier = false) {
|
||||
console.log({carrier});
|
||||
return ship_types.filter((c) => carrier == !!c.carrier).filter((c) => c.mass[0] <= mass).filter((c) => c.mass[1] >= mass);
|
||||
export function candidateShipTypes(mass = 0, carrier = false) {
|
||||
return ship_types
|
||||
.filter((c) => carrier == !!c.carrier)
|
||||
.filter((c) => c.mass[0] <= mass)
|
||||
.filter((c) => c.mass[1] >= mass);
|
||||
}
|
21
src/lib/components/ShipEdit/ShipEdit.stories.svelte
Normal file
21
src/lib/components/ShipEdit/ShipEdit.stories.svelte
Normal file
@ -0,0 +1,21 @@
|
||||
<Meta title="ShipEdit" component={ShipEdit} argTypes={{}} />
|
||||
|
||||
<Story name="Primary" args={{}} />
|
||||
|
||||
<Template let:args>
|
||||
<div style="width: 50em">
|
||||
<ShipEdit />
|
||||
</div>
|
||||
</Template>
|
||||
|
||||
<script>
|
||||
import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
|
||||
import { setContext } from "svelte";
|
||||
|
||||
import ShipEdit from "./index.svelte";
|
||||
import shipStore from "$lib/store/ship.js";
|
||||
|
||||
setContext("ship", shipStore());
|
||||
</script>
|
12
src/lib/components/ShipEdit/index.svelte
Normal file
12
src/lib/components/ShipEdit/index.svelte
Normal file
@ -0,0 +1,12 @@
|
||||
<Identification {...$shipState.identification} {...$shipState.reqs} />
|
||||
|
||||
<script>
|
||||
import { getContext } from "svelte";
|
||||
|
||||
import Identification from "./Identification/index.svelte";
|
||||
|
||||
const { state: shipState } = getContext("ship");
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
@ -1,49 +0,0 @@
|
||||
<div>
|
||||
<Field
|
||||
label="ship class"
|
||||
value={general.ship_class}
|
||||
on:change={change_class}
|
||||
/>
|
||||
|
||||
<Field label="ship type">
|
||||
<select value={ship_type} on:change={change_ship_type}>
|
||||
{#each ship_types as type (type)}
|
||||
<option>{type}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import { getContext } from "svelte";
|
||||
|
||||
import Field from "$lib/components/Field/index.svelte";
|
||||
import { candidate_ship_types } from "../../dux/ship_types";
|
||||
|
||||
export let ship = getContext("ship");
|
||||
let general;
|
||||
$: general = $ship.general;
|
||||
|
||||
const change_class = (event) =>
|
||||
ship.dispatch(ship.actions.set_ship_class(event.target.value));
|
||||
|
||||
let ship_type;
|
||||
$: ship_type = $ship.general.ship_type;
|
||||
|
||||
const change_ship_type = ({ target: { value } }) =>
|
||||
ship.dispatch.set_ship_type(value);
|
||||
|
||||
let ship_types;
|
||||
$: ship_types = candidate_ship_types(
|
||||
$ship.general.mass,
|
||||
$ship.carrier.bays > 0
|
||||
).map(({ name }) => name);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div {
|
||||
display: flex;
|
||||
align-items: end;
|
||||
gap: 2em;
|
||||
}
|
||||
</style>
|
@ -6,9 +6,3 @@
|
||||
import Identification from "./Identification.svelte";
|
||||
import ShipCost from "./ShipCost.svelte";
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div {
|
||||
background-color: red;
|
||||
}
|
||||
</style>
|
||||
|
28
src/lib/shipDux/engine.js
Normal file
28
src/lib/shipDux/engine.js
Normal file
@ -0,0 +1,28 @@
|
||||
import { Updux } from "updux";
|
||||
import u from "updeep";
|
||||
|
||||
import reqs from "./reqs.js";
|
||||
|
||||
const dux = new Updux({
|
||||
subduxes: { reqs },
|
||||
initial: {
|
||||
rating: 1,
|
||||
advanced: false,
|
||||
},
|
||||
actions: {
|
||||
setEngine: null,
|
||||
setEngineReqs: null,
|
||||
},
|
||||
});
|
||||
|
||||
dux.setMutation("setEngine", (changes) => u(changes));
|
||||
dux.setMutation("setEngineReqs", (reqs) => u({ reqs }));
|
||||
|
||||
export function calcDriveReqs(shipMass, rating, advanced = false) {
|
||||
const mass = Math.ceil(rating * 0.05 * shipMass);
|
||||
const cost = mass * (advanced ? 3 : 2);
|
||||
|
||||
return { mass, cost };
|
||||
}
|
||||
|
||||
export default dux;
|
20
src/lib/shipDux/identification.js
Normal file
20
src/lib/shipDux/identification.js
Normal file
@ -0,0 +1,20 @@
|
||||
import { Updux } from "updux";
|
||||
import u from "updeep";
|
||||
|
||||
const dux = new Updux({
|
||||
actions: {
|
||||
setShipType: null,
|
||||
setShipClass: null,
|
||||
},
|
||||
initial: {
|
||||
shipType: "",
|
||||
shipClass: "",
|
||||
isCarrier: false,
|
||||
mass: 10,
|
||||
},
|
||||
});
|
||||
|
||||
dux.setMutation("setShipType", (shipType) => u({ shipType }));
|
||||
dux.setMutation("setShipClass", (shipClass) => u({ shipClass }));
|
||||
|
||||
export default dux;
|
17
src/lib/shipDux/index.js
Normal file
17
src/lib/shipDux/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
import { Updux } from "updux";
|
||||
|
||||
import engine from "./engine.js";
|
||||
import identification from "./identification.js";
|
||||
import reqs from "./reqs.js";
|
||||
|
||||
const dux = new Updux({
|
||||
subduxes: {
|
||||
identification,
|
||||
engine,
|
||||
},
|
||||
initial: {
|
||||
reqs: { cost: 0, mass: 10 },
|
||||
},
|
||||
});
|
||||
|
||||
export default dux;
|
10
src/lib/shipDux/reqs.js
Normal file
10
src/lib/shipDux/reqs.js
Normal file
@ -0,0 +1,10 @@
|
||||
import { Updux } from "updux";
|
||||
|
||||
const dux = new Updux({
|
||||
initial: {
|
||||
cost: 0,
|
||||
mass: 0,
|
||||
},
|
||||
});
|
||||
|
||||
export default dux;
|
32
src/lib/store/ship.js
Normal file
32
src/lib/store/ship.js
Normal file
@ -0,0 +1,32 @@
|
||||
import { browser } from "$app/env";
|
||||
import { readable, get } from "svelte/store";
|
||||
import { compose, applyMiddleware } from "redux";
|
||||
|
||||
import shipDux from "../shipDux/index.js";
|
||||
|
||||
let composeEnhancers = compose;
|
||||
|
||||
if (browser) {
|
||||
composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__;
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const duxStore = shipDux.createStore(undefined, (mw) =>
|
||||
composeEnhancers(applyMiddleware(mw))
|
||||
);
|
||||
|
||||
let previous;
|
||||
const state = readable(duxStore.getState(), (set) => {
|
||||
duxStore.subscribe(() => {
|
||||
if (previous === duxStore.getState()) return;
|
||||
previous = duxStore.getState();
|
||||
console.log("Setting!", previous);
|
||||
set(previous);
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
dispatch: duxStore.dispatch,
|
||||
state,
|
||||
};
|
||||
};
|
Loading…
Reference in New Issue
Block a user