]> git.localhorst.tv Git - alttp.git/blobdiff - resources/js/components/tracker/Map.js
update dunka/muffins tracker
[alttp.git] / resources / js / components / tracker / Map.js
index 9c27a3476ff938d7ce4a56be9ae642d67e00c7df..3ee4b2f81458ab4eeb6190273623467406788bc1 100644 (file)
@@ -3,11 +3,21 @@ import React from 'react';
 import { useTranslation } from 'react-i18next';
 
 import {
+       addDungeonCheck,
+       aggregateDungeonStatus,
+       aggregateLocationStatus,
        clearAll,
-       decrement,
+       completeDungeonChecks,
+       countRemainingLocations,
+       getDungeonClearedItems,
+       getDungeonRemainingItems,
        hasDungeonBoss,
-       increment,
-       toggleBoolean,
+       hasDungeonPrize,
+       isDungeonCleared,
+       removeDungeonCheck,
+       resetDungeonChecks,
+       setBossDefeated,
+       setPrizeAcquired,
        unclearAll,
 } from '../../helpers/tracker';
 import { useTracker } from '../../hooks/tracker';
@@ -636,8 +646,8 @@ const Location = ({ number, l, size }) => {
        >
                <title>{t(`tracker.location.${l.id}`)}</title>
                <rect className="box" x="0" y="0" />
-               {number && l.cleared < l.total ?
-                       <text className="text" x="0" y="0">{Math.max(0, l.total - l.cleared)}</text>
+               {number && l.remaining ?
+                       <text className="text" x="0" y="0">{l.remaining}</text>
                : null}
        </g>;
 };
@@ -648,8 +658,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,
@@ -677,91 +687,87 @@ const makeBackground = (src, level) => {
 };
 
 const Map = () => {
-       const { dungeons, setState, state } = useTracker();
+       const { dungeons, logic, setManualState, state } = useTracker();
 
        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;
-               let status = 'available';
-               if (cleared === total) {
-                       if (['ct', 'gt'].includes(dungeon.id)) {
-                               if (hasDungeonBoss(state, dungeon)) {
-                                       status = 'cleared';
-                               }
-                       } else {
-                               status = 'cleared';
-                       }
-               }
+               const remaining = getDungeonRemainingItems(state, definition);
+               const status = aggregateDungeonStatus(definition, logic, state);
                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)) {
+                                       setManualState(addDungeonCheck(definition));
+                               } else if (
+                                       !hasDungeonBoss(state, definition) || !hasDungeonPrize(state, definition)
+                               ) {
+                                       if (definition.boss) {
+                                               setManualState(setBossDefeated(definition, true));
+                                       }
+                                       if (definition.prize) {
+                                               setManualState(setPrizeAcquired(definition, true));
                                        }
                                } else {
-                                       setState(increment(`${dungeon.id}-checks`, total));
+                                       setManualState(resetDungeonChecks(definition));
+                                       if (definition.boss) {
+                                               setManualState(setBossDefeated(definition, false));
+                                       }
+                                       if (definition.prize) {
+                                               setManualState(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) {
+                                               setManualState(removeDungeonCheck(definition));
+                                       }
+                                       if (definition.boss) {
+                                               setManualState(setBossDefeated(definition, false));
+                                       }
+                                       if (definition.prize) {
+                                               setManualState(setPrizeAcquired(definition, false));
                                        }
+                               } else if (getDungeonClearedItems(state, definition)) {
+                                       setManualState(removeDungeonCheck(definition));
                                } else {
-                                       setState(decrement(`${dungeon.id}-checks`, total));
+                                       setManualState(completeDungeonChecks(definition));
+                                       if (definition.boss) {
+                                               setManualState(setBossDefeated(definition, true));
+                                       }
+                                       if (definition.prize) {
+                                               setManualState(setPrizeAcquired(definition, true));
+                                       }
                                }
                        },
                };
-       }, [dungeons, setState, state]);
+       }, [dungeons, logic, setManualState, state]);
 
        const mapLocation = React.useCallback(loc => {
-               const cleared = loc.checks.reduce((acc, cur) => state[cur] ? acc + 1 : acc, 0);
-               const total = loc.checks.length;
-               let status = 'available';
-               if (cleared === total) {
-                       status = 'cleared';
-               }
+               const remaining = countRemainingLocations(state, loc.checks);
+               const status = aggregateLocationStatus(loc.checks, logic, state);
                return {
                        ...loc,
-                       cleared,
-                       total,
+                       remaining,
                        status,
                        handlePrimary: () => {
-                               if (cleared < total) {
-                                       setState(clearAll(loc.checks));
+                               if (remaining) {
+                                       setManualState(clearAll(loc.checks));
                                } else {
-                                       setState(unclearAll(loc.checks));
+                                       setManualState(unclearAll(loc.checks));
                                }
                        },
                        handleSecondary: () => {
-                               if (cleared < total) {
-                                       setState(clearAll(loc.checks));
+                               if (remaining) {
+                                       setManualState(clearAll(loc.checks));
                                } else {
-                                       setState(unclearAll(loc.checks));
+                                       setManualState(unclearAll(loc.checks));
                                }
                        },
                };
-       }, [setState, state]);
+       }, [logic, setManualState, state]);
 
        const lwDungeons = React.useMemo(() => LW_DUNGEONS.map(mapDungeon), [mapDungeon]);
        const lwLocations = React.useMemo(() => LW_LOCATIONS.map(mapLocation), [mapLocation]);