From: Daniel Karbach Date: Mon, 25 Mar 2024 17:52:18 +0000 (+0100) Subject: clean up manual tracking X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=24489254a5d05efd6fe7dceb2cffe5fdb49ab7b7;p=alttp.git clean up manual tracking --- diff --git a/resources/js/components/tracker/Dungeons.js b/resources/js/components/tracker/Dungeons.js index 07b6638..08a581f 100644 --- a/resources/js/components/tracker/Dungeons.js +++ b/resources/js/components/tracker/Dungeons.js @@ -2,6 +2,10 @@ import React from 'react'; import CountDisplay from './CountDisplay'; import ToggleIcon from './ToggleIcon'; +import { + getDungeonAcquiredSKs, + getDungeonRemainingItems, +} from '../../helpers/tracker'; import { useTracker } from '../../hooks/tracker'; const Dungeons = () => { @@ -24,7 +28,7 @@ const Dungeons = () => { controller={ToggleIcon.dungeonCountController(dungeon, dungeon.sk)} icons={['small-key']} /> - + { /> - + {dungeon.boss ? { > {t(`tracker.location.${l.id}`)} - {number && l.cleared < l.total ? - {Math.max(0, l.total - l.cleared)} + {number && l.remaining ? + {l.remaining} : null} ; }; @@ -649,8 +657,8 @@ Location.propTypes = { id: PropTypes.string, x: PropTypes.number, y: PropTypes.number, - cleared: PropTypes.number, - total: PropTypes.number, + number: PropTypes.number, + remaining: PropTypes.number, status: PropTypes.string, handlePrimary: PropTypes.func, handleSecondary: PropTypes.func, @@ -682,8 +690,7 @@ const Map = () => { const mapDungeon = React.useCallback(dungeon => { const definition = dungeons.find(d => d.id === dungeon.id); - const cleared = state[`${dungeon.id}-checks`] || 0; - const total = definition.items; + const remaining = getDungeonRemainingItems(state, definition); let status = 'available'; if (isDungeonCleared(state, definition)) { status = 'cleared'; @@ -691,65 +698,74 @@ const Map = () => { return { ...dungeon, status, - cleared, - total, + remaining, handlePrimary: () => { - if (['ct', 'gt'].includes(dungeon.id) && cleared === total) { - if (hasDungeonBoss(state, dungeon)) { - // reset - setState(s => ({ - ...s, - [`${dungeon.id}-checks`]: 0, - [`${dungeon.id}-boss-defeated`]: false, - })); - } else { - setState(toggleBoolean(`${dungeon.id}-boss-defeated`)); + if (getDungeonRemainingItems(state, definition)) { + setState(addDungeonCheck(definition)); + } else if ( + !hasDungeonBoss(state, definition) || !hasDungeonPrize(state, definition) + ) { + if (definition.boss) { + setState(setBossDefeated(definition, true)); + } + if (definition.prize) { + setState(setPrizeAcquired(definition, true)); } } else { - setState(increment(`${dungeon.id}-checks`, total)); + setState(resetDungeonChecks(definition)); + if (definition.boss) { + setState(setBossDefeated(definition, false)); + } + if (definition.prize) { + setState(setPrizeAcquired(definition, false)); + } } }, handleSecondary: () => { - if (['ct', 'gt'].includes(dungeon.id) && - (hasDungeonBoss(state, dungeon) || !cleared) - ) { - if (hasDungeonBoss(state, dungeon)) { - setState(toggleBoolean(`${dungeon.id}-boss-defeated`)); - } else { - setState(s => ({ - ...s, - [`${dungeon.id}-checks`]: total, - [`${dungeon.id}-boss-defeated`]: true, - })); + if (isDungeonCleared(state, definition)) { + if (definition.items) { + setState(removeDungeonCheck(definition)); } + if (definition.boss) { + setState(setBossDefeated(definition, false)); + } + if (definition.prize) { + setState(setPrizeAcquired(definition, false)); + } + } else if (getDungeonClearedItems(state, definition)) { + setState(removeDungeonCheck(definition)); } else { - setState(decrement(`${dungeon.id}-checks`, total)); + setState(completeDungeonChecks(definition)); + if (definition.boss) { + setState(setBossDefeated(definition, true)); + } + if (definition.prize) { + setState(setPrizeAcquired(definition, true)); + } } }, }; }, [dungeons, setState, state]); const mapLocation = React.useCallback(loc => { - const cleared = loc.checks.reduce((acc, cur) => state[cur] ? acc + 1 : acc, 0); - const total = loc.checks.length; + const remaining = countRemainingLocations(state, loc.checks); let status = 'available'; - if (cleared === total) { + if (hasClearedLocations(state, loc.checks)) { status = 'cleared'; } return { ...loc, - cleared, - total, + remaining, status, handlePrimary: () => { - if (cleared < total) { + if (remaining) { setState(clearAll(loc.checks)); } else { setState(unclearAll(loc.checks)); } }, handleSecondary: () => { - if (cleared < total) { + if (remaining) { setState(clearAll(loc.checks)); } else { setState(unclearAll(loc.checks)); diff --git a/resources/js/components/tracker/ToggleIcon.js b/resources/js/components/tracker/ToggleIcon.js index 3f6af96..f7cc074 100644 --- a/resources/js/components/tracker/ToggleIcon.js +++ b/resources/js/components/tracker/ToggleIcon.js @@ -3,14 +3,18 @@ import React from 'react'; import ZeldaIcon from '../common/ZeldaIcon'; import { + addDungeonCheck, decrement, getDungeonBoss, + getDungeonRemainingItems, getDungeonPrize, hasDungeonBoss, hasDungeonPrize, highestActive, increment, + removeDungeonCheck, toggleBoolean, + toggleBossDefeated, } from '../../helpers/tracker'; import { useTracker } from '../../hooks/tracker'; @@ -110,23 +114,23 @@ ToggleIcon.dungeonBossController = (dungeon) => ({ handlePrimary: dungeon.bosses.length > 1 ? nextString(`${dungeon.id}-boss`) : (state, setState) => { - setState(toggleBoolean(`${dungeon.id}-boss-defeated`)); + setState(toggleBossDefeated(dungeon)); }, handleSecondary: dungeon.bosses.length > 1 ? previousString(`${dungeon.id}-boss`) : (state, setState) => { - setState(toggleBoolean(`${dungeon.id}-boss-defeated`)); + setState(toggleBossDefeated(dungeon)); }, }); -ToggleIcon.dungeonCheckController = (dungeon, max) => ({ - getActive: (state, icons) => state[`${dungeon.id}-checks`] < max ? icons[1] : null, +ToggleIcon.dungeonCheckController = (dungeon) => ({ + getActive: (state, icons) => getDungeonRemainingItems(state, dungeon) ? icons[1] : null, getDefault: firstIcon, handlePrimary: (state, setState) => { - setState(increment(`${dungeon.id}-checks`, max)); + setState(addDungeonCheck(dungeon)); }, handleSecondary: (state, setState) => { - setState(decrement(`${dungeon.id}-checks`, max)); + setState(removeDungeonCheck(dungeon)); }, }); diff --git a/resources/js/helpers/tracker.js b/resources/js/helpers/tracker.js index 92508d4..bc18847 100644 --- a/resources/js/helpers/tracker.js +++ b/resources/js/helpers/tracker.js @@ -1598,24 +1598,59 @@ export const unclearAll = names => state => { return { ...state, ...changes }; }; -export const hasDungeonBoss = (state, dungeon) => !!state[`${dungeon.id}-boss-defeated`]; +export const countClearedLocations = (state, locations) => + locations.reduce((acc, cur) => state[cur] ? acc + 1 : acc, 0); + +export const hasClearedLocations = (state, locations) => + countClearedLocations(state, locations) === locations.length; + +export const countRemainingLocations = (state, locations) => + locations.reduce((acc, cur) => state[cur] ? acc : acc + 1, 0); + +export const hasDungeonBoss = (state, dungeon) => + !dungeon.boss || !!state[`${dungeon.id}-boss-defeated`]; export const getDungeonBoss = (state, dungeon) => state[`${dungeon.id}-boss`] || dungeon.boss || null; -export const hasDungeonPrize = (state, dungeon) => !!state[`${dungeon.id}-prize-acquired`]; +export const hasDungeonPrize = (state, dungeon) => + !dungeon.prize || !!state[`${dungeon.id}-prize-acquired`]; export const getDungeonPrize = (state, dungeon) => state[`${dungeon.id}-prize`] || null; +export const getDungeonClearedItems = (state, dungeon) => state[`${dungeon.id}-checks`] || 0; + +export const getDungeonRemainingItems = (state, dungeon) => + Math.max(0, dungeon.items - getDungeonClearedItems(state, dungeon)); + +export const getDungeonAcquiredSKs = (state, dungeon) => state[`${dungeon.id}-small-key`] || 0; + export const isDungeonCleared = (state, dungeon) => { - const cleared = state[`${dungeon.id}-checks`] || 0; - const total = dungeon.items; - const hasItems = cleared >= total; - const hasBoss = !dungeon.boss || hasDungeonBoss(state, dungeon); - const hasPrize = !dungeon.porize || hasDungeonPrize(state, dungeon); + const hasItems = !getDungeonRemainingItems(state, dungeon); + const hasBoss = hasDungeonBoss(state, dungeon); + const hasPrize = hasDungeonPrize(state, dungeon); return hasItems && hasBoss && hasPrize; }; +export const toggleBossDefeated = dungeon => toggleBoolean(`${dungeon.id}-boss-defeated`); + +export const setBossDefeated = (dungeon, defeated) => + state => ({ ...state, [`${dungeon.id}-boss-defeated`]: !!defeated }); + +export const togglePrizeAcquired = dungeon => toggleBoolean(`${dungeon.id}-prize-acquired`); + +export const setPrizeAcquired = (dungeon, acquired) => + state => ({ ...state, [`${dungeon.id}-prize-acquired`]: !!acquired }); + +export const addDungeonCheck = dungeon => increment(`${dungeon.id}-checks`, dungeon.items); + +export const removeDungeonCheck = dungeon => decrement(`${dungeon.id}-checks`, dungeon.items); + +export const resetDungeonChecks = dungeon => state => ({ ...state, [`${dungeon.id}-checks`]: 0 }); + +export const completeDungeonChecks = dungeon => + state => ({ ...state, [`${dungeon.id}-checks`]: dungeon.items }); + export const makeEmptyState = () => { const state = {}; BOOLEAN_STATES.forEach(p => {