This commit is contained in:
Joshua Seigler 2025-04-16 14:12:23 -07:00
parent f67606b944
commit 1e71255371
9 changed files with 389 additions and 335 deletions

View file

@ -1,24 +1,15 @@
import { makePersisted } from "@solid-primitives/storage";
import connections from "./assets/connections.json";
import { shuffleArray } from "./utils";
import { createStore } from "solid-js/store";
import { tauriStorage } from "@solid-primitives/storage/tauri";
type Connection = (typeof connections)[number];
type Answer = Connection["answers"][number];
function fromIndex(index: number): [number, number] {
const col = index % 4;
const row = (index - col) / 4;
return [row, col];
type Solution = {
id: number
mistakes: number
}
type AppStore = {
puzzleId: number;
pinnedCount: number;
selected: number[];
solvedGroups: Answer[];
puzzle: number[];
solutions: Solution[]
};
export default function useAppModel() {
@ -26,138 +17,23 @@ export default function useAppModel() {
"__TAURI_INTERNALS__" in window ? tauriStorage("AppStore") : localStorage;
const [store, setStore] = makePersisted(
createStore<AppStore>({
puzzleId: 1,
pinnedCount: 0,
selected: [],
solvedGroups: [],
puzzle: shuffleArray(Array.from({ length: 16 }, (_, i) => i)),
solutions: []
}),
{
name: "slick-connections",
storage,
serialize(data) {
return JSON.stringify({
...data,
selected: [],
});
},
}
);
const answers = (): Answer[] => {
return connections.find((x) => x.id === store.puzzleId)!.answers;
};
const handleSelectGame = (newId: number) => {
setStore({
puzzleId: newId,
selected: [],
pinnedCount: 0,
puzzle: shuffleArray(Array.from({ length: 16 }, (_, i) => i)),
solvedGroups: [],
});
};
const getFromPuzzle = (index: number) => {
const puzzleIndex = store.puzzle[index];
const [groupIndex, memberIndex] = fromIndex(puzzleIndex);
const group = answers()[groupIndex];
return {
group: group.group,
level: group.level,
answer: answers()[groupIndex].members[memberIndex],
};
};
const handleGuess = () => {
const selected = store.puzzle.length === 4 ? [0, 1, 2, 3] : store.selected;
const selectedAnswers = selected.map((x) => getFromPuzzle(x));
const { level } = selectedAnswers[0];
const isCorrect = selectedAnswers.every((x) => x.level === level);
if (!isCorrect) {
// TODO you got it wrong
alert("wrong");
return;
}
const selectedPinnedCount = selected.reduce(
(acc, cur) => acc + (cur < store.pinnedCount ? 1 : 0),
0
);
setStore({
pinnedCount: store.pinnedCount - selectedPinnedCount,
puzzle: store.puzzle.filter((x) =>
selected.every((s) => store.puzzle[s] !== x)
),
selected: [],
});
const newSolvedGroup = answers().find((x) => x.level === level);
if (newSolvedGroup != null) {
setStore({
solvedGroups: [...store.solvedGroups, newSolvedGroup],
});
}
if (store.puzzle.length === 0) {
// completely solved!
}
};
const handleShuffle = () => {
const pinned = store.puzzle.slice(0, store.pinnedCount);
const toShuffle = store.puzzle.slice(store.pinnedCount);
setStore({
puzzle: [...pinned, ...shuffleArray(toShuffle)],
});
};
const handleDeselect = () => {
setStore({
selected: [],
});
};
const handlePinUnpin = () => {
if (store.selected.every((x) => x < store.pinnedCount)) {
// we are unpinning
const puzzleStart = Array.from({ length: store.pinnedCount }, (_, i) => i)
.filter((x) => !store.selected.includes(x))
.map((x) => store.puzzle[x]);
const puzzleMiddle = store.selected.map((x) => store.puzzle[x]);
const puzzleEnd = store.puzzle.slice(store.pinnedCount);
const newPuzzle = [...puzzleStart, ...puzzleMiddle, ...puzzleEnd];
setStore({
pinnedCount: store.pinnedCount - store.selected.length,
selected: [],
puzzle: newPuzzle,
});
return;
}
// we are pinning
const puzzleStart = store.puzzle.slice(0, store.pinnedCount);
const puzzleMid = store.selected
.filter((x) => x >= store.pinnedCount)
.map((x) => store.puzzle[x]);
const puzzleEnd = Array.from(
{ length: store.puzzle.length - store.pinnedCount },
(_, i) => i + store.pinnedCount
)
.filter((x) => !store.selected.includes(x))
.map((x) => store.puzzle[x]);
setStore({
pinnedCount: puzzleStart.length + puzzleMid.length,
selected: [],
puzzle: [...puzzleStart, ...puzzleMid, ...puzzleEnd],
});
};
function setSolution(id: number, mistakes: number) {
setStore("solutions", id, {
id,
mistakes
})
}
return {
connections,
store,
setStore,
handleGuess,
handlePinUnpin,
handleSelectGame,
handleShuffle,
handleDeselect,
getFromPuzzle,
setSolution,
};
}