--- /dev/null
+import FuzzySearch from 'fuzzy-search';
+import PropTypes from 'prop-types';
+import React from 'react';
+
+const AREAS = [
+ {
+ id: 'kf',
+ bgColor: '#6aa84f',
+ fgColor: '#000000',
+ name: 'Kokiri Forest',
+ short: 'KF',
+ entrances: [
+ {
+ id: 'bro',
+ bgColor: '#b6d7a8',
+ fgColor: '#000000',
+ name: 'Brothers\' House',
+ short: 'Bros',
+ },
+ {
+ id: 'link',
+ bgColor: '#b6d7a8',
+ fgColor: '#000000',
+ name: 'Link\'s House',
+ short: 'Links',
+ },
+ {
+ id: 'sariah',
+ bgColor: '#b6d7a8',
+ fgColor: '#000000',
+ name: 'Sariah\'s House',
+ short: 'Sariahs',
+ },
+ {
+ id: 'twin',
+ bgColor: '#b6d7a8',
+ fgColor: '#000000',
+ name: 'Twins\' House',
+ short: 'Twins',
+ },
+ {
+ id: 'shop',
+ bgColor: '#b6d7a8',
+ fgColor: '#000000',
+ name: 'Shop',
+ short: 'Shop',
+ },
+ {
+ id: 'mido',
+ bgColor: '#b6d7a8',
+ fgColor: '#000000',
+ name: 'Mido\'s House',
+ short: 'Mido',
+ },
+ {
+ id: 'deku',
+ bgColor: '#ead1dc',
+ fgColor: '#000000',
+ name: 'Deku Tree',
+ short: 'Deku',
+ spacer: true,
+ },
+ {
+ id: 'storms',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Storms Grotto',
+ short: 'Storms Grotto',
+ },
+ {
+ id: 'hf',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Hyrule Field',
+ short: 'HF',
+ },
+ {
+ id: 'lw',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Lost Woods',
+ short: 'LW',
+ },
+ ],
+ },
+ {
+ id: 'lw',
+ bgColor: '#38761d',
+ fgColor: '#000000',
+ name: 'Lost Woods',
+ short: 'LW',
+ entrances: [
+ {
+ id: 'gcg',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'GC Grotto',
+ short: 'GC Grotto',
+ },
+ {
+ id: 'tg',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Theater Grotto',
+ short: 'Theater Grotto',
+ },
+ {
+ id: 'sfmg',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'SFM Grotto',
+ short: 'SFM Grotto',
+ },
+ {
+ id: 'kf',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Kokiri Forest',
+ short: 'KF',
+ spacer: true,
+ },
+ {
+ id: 'gc',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Goron City',
+ short: 'GC',
+ },
+ {
+ id: 'zr',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Zora\'s River',
+ short: 'ZR',
+ },
+ {
+ id: 'sfm',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Sacred Forest Maedows',
+ short: 'SFM',
+ },
+ ],
+ },
+ {
+ id: 'sfm',
+ bgColor: '#274e13',
+ fgColor: '#000000',
+ name: 'Sacred Forest Maedows',
+ short: 'SFM',
+ entrances: [
+ {
+ id: 'forest',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Forest Temple',
+ short: 'Forest Temple',
+ },
+ {
+ id: 'wolf',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Wolf Grotto',
+ short: 'Wolf Grotto',
+ },
+ {
+ id: 'fairy',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Fairy Grotto',
+ short: 'Fairy Grotto',
+ },
+ {
+ id: 'storms',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Storms Grotto',
+ short: 'Storms Grotto',
+ },
+ {
+ id: 'lw',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Lost Woods',
+ short: 'LW',
+ },
+ ],
+ },
+ {
+ id: 'gy',
+ bgColor: '#a64d79',
+ fgColor: '#000000',
+ name: 'Graveyard',
+ short: 'Grave',
+ entrances: [
+ {
+ id: 'dh',
+ bgColor: '#c27ba0',
+ fgColor: '#000000',
+ name: 'Dampe Hut',
+ short: 'Dampe Hut',
+ },
+ {
+ id: 'shadow',
+ bgColor: '#c27ba0',
+ fgColor: '#000000',
+ name: 'Shadow Temple',
+ short: 'Shadow',
+ },
+ {
+ id: 'shield',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Shield Grave',
+ short: 'Shield Grave',
+ },
+ {
+ id: 'race',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Dampe Race',
+ short: 'Dampe Race',
+ },
+ {
+ id: 'sun',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Sun Song Grave',
+ short: 'Sun Song Gr',
+ },
+ {
+ id: 'family',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Family Tomb',
+ short: 'Family Tomb',
+ },
+ {
+ id: 'kak',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Kakariko',
+ short: 'Kak',
+ },
+ ],
+ },
+ {
+ id: 'kak',
+ bgColor: '#ff9900',
+ fgColor: '#000000',
+ name: 'Kakariko Village',
+ short: 'Kak',
+ entrances: [
+ {
+ id: 'talon',
+ bgColor: '#f9cb9c',
+ fgColor: '#000000',
+ name: 'Talon\'s House',
+ short: 'Talons',
+ },
+ {
+ id: 'skull',
+ bgColor: '#f9cb9c',
+ fgColor: '#000000',
+ name: 'Skulltula House',
+ short: 'Skulltula',
+ },
+ {
+ id: 'impaf',
+ bgColor: '#f9cb9c',
+ fgColor: '#000000',
+ name: 'Impa Front',
+ short: 'Impa Front',
+ },
+ {
+ id: 'impab',
+ bgColor: '#f9cb9c',
+ fgColor: '#000000',
+ name: 'Impa Back',
+ short: 'Impa Back',
+ },
+ {
+ id: 'shield',
+ bgColor: '#f9cb9c',
+ fgColor: '#000000',
+ name: 'Shield Shop',
+ short: 'Shield Shop',
+ },
+ {
+ id: 'potion',
+ bgColor: '#f9cb9c',
+ fgColor: '#000000',
+ name: 'Potion Shop',
+ short: 'Potion Shop',
+ },
+ {
+ id: 'back',
+ bgColor: '#f9cb9c',
+ fgColor: '#000000',
+ name: 'Shop Back',
+ short: 'Shop Back',
+ },
+ {
+ id: 'witch',
+ bgColor: '#f9cb9c',
+ fgColor: '#000000',
+ name: 'Witch',
+ short: 'Witch',
+ },
+ {
+ id: 'arch',
+ bgColor: '#f9cb9c',
+ fgColor: '#000000',
+ name: 'Archery',
+ short: 'Archery',
+ },
+ {
+ id: 'mill',
+ bgColor: '#f9cb9c',
+ fgColor: '#000000',
+ name: 'Windmill',
+ short: 'Windmill',
+ },
+ {
+ id: 'botw',
+ bgColor: '#a64d79',
+ fgColor: '#000000',
+ name: 'Bottom of the Well',
+ short: 'Bottom Well',
+ spacer: true,
+ },
+ {
+ id: 'open',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Open Grotto',
+ short: 'Open Grotto',
+ },
+ {
+ id: 'redead',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Redead Grotto',
+ short: 'Redead Grotto',
+ },
+ {
+ id: 'hf',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Hyrule Field',
+ short: 'HF',
+ },
+ {
+ id: 'dmt',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Death Mountain Trail',
+ short: 'DMT',
+ },
+ {
+ id: 'gy',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Graveyard',
+ short: 'Grave',
+ },
+ ],
+ },
+ {
+ id: 'm1',
+ bgColor: '#9900ff',
+ fgColor: '#000000',
+ name: 'Market 1',
+ short: 'M1',
+ entrances: [
+ {
+ id: 'shield',
+ bgColor: '#b4a7d6',
+ fgColor: '#000000',
+ name: 'Shield Shop',
+ short: 'Shield Shop',
+ },
+ {
+ id: 'potion',
+ bgColor: '#b4a7d6',
+ fgColor: '#000000',
+ name: 'Potion Shop',
+ short: 'Potion Shop',
+ },
+ {
+ id: 'mask',
+ bgColor: '#b4a7d6',
+ fgColor: '#000000',
+ name: 'Mask Shop',
+ short: 'Mask Shop',
+ },
+ {
+ id: 'sling',
+ bgColor: '#b4a7d6',
+ fgColor: '#000000',
+ name: 'Slingshot/Arrow Game',
+ short: 'Sling Game',
+ },
+ {
+ id: 'chuu',
+ bgColor: '#b4a7d6',
+ fgColor: '#000000',
+ name: 'Bombchu Bowling',
+ short: 'Bombchu',
+ },
+ {
+ id: 'tcg',
+ bgColor: '#b4a7d6',
+ fgColor: '#000000',
+ name: 'Treasure Chest Game',
+ short: 'TCG',
+ },
+ {
+ id: 'alleyl',
+ bgColor: '#b4a7d6',
+ fgColor: '#000000',
+ name: 'Backalley Left',
+ short: 'Alley L',
+ },
+ {
+ id: 'alleyr',
+ bgColor: '#b4a7d6',
+ fgColor: '#000000',
+ name: 'Backalley Right',
+ short: 'Alley R',
+ },
+ {
+ id: 'tot',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Temple of Time',
+ short: 'ToT',
+ },
+ {
+ id: 'hc',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Hyrule Castle',
+ short: 'HC',
+ },
+ {
+ id: 'm2',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Market 2',
+ short: 'M2',
+ },
+ ],
+ },
+ {
+ id: 'm2',
+ bgColor: '#9900ff',
+ fgColor: '#000000',
+ name: 'Market 2',
+ short: 'M2',
+ entrances: [
+ {
+ id: 'bp',
+ bgColor: '#b4a7d6',
+ fgColor: '#000000',
+ name: 'Big Poe',
+ short: 'Big Poe',
+ },
+ {
+ id: 'hf',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Hyrule Field',
+ short: 'HF',
+ },
+ {
+ id: 'm1',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Market 1',
+ short: 'M1',
+ },
+ ],
+ },
+ {
+ id: 'hc',
+ bgColor: '#bf9000',
+ fgColor: '#000000',
+ name: 'Hyrule Castle',
+ short: 'HC',
+ entrances: [
+ {
+ id: 'hcfairy',
+ bgColor: '#b4a7d6',
+ fgColor: '#000000',
+ name: 'Hyrule Castle Fairy',
+ short: 'HC Fairy',
+ },
+ {
+ id: 'gfairy',
+ bgColor: '#b4a7d6',
+ fgColor: '#000000',
+ name: 'Ganon\'s Castle Fairy',
+ short: 'Ganon Fairy',
+ },
+ {
+ id: 'igc',
+ bgColor: '#b4a7d6',
+ fgColor: '#000000',
+ name: 'Inside Ganon\'s Castle',
+ short: 'IGC',
+ },
+ {
+ id: 'storms',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Storms Grotto',
+ short: 'Storms Grotto',
+ },
+ {
+ id: 'm1',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Market 1',
+ short: 'M1',
+ },
+ ],
+ },
+ {
+ id: 'hf',
+ bgColor: '#674ea7',
+ fgColor: '#000000',
+ name: 'Hyrule Field',
+ short: 'HF',
+ entrances: [
+ {
+ id: 'destiny',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Destiny Grotto',
+ short: 'Destiny Grotto',
+ },
+ {
+ id: 'tektite',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Tektite Grotto',
+ short: 'Tektite',
+ },
+ {
+ id: 'nw',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Northwest Grotto',
+ short: 'NW Grotto',
+ },
+ {
+ id: 'nk',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Grotto near Kakariko',
+ short: 'near Kak Gro',
+ },
+ {
+ id: 'se',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Southeast Grotto',
+ short: 'SE Grotto',
+ },
+ {
+ id: 'open',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Open Grotto',
+ short: 'Open Grotto',
+ },
+ {
+ id: 'sg',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'South Grotto',
+ short: 'South Grotto',
+ },
+ {
+ id: 'cow',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Cow Grotto',
+ short: 'Cow Grotto',
+ },
+ {
+ id: 'town',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Town',
+ short: 'Town',
+ spacer: true,
+ },
+ {
+ id: 'llr',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Lon Lon Ranch',
+ short: 'LLR',
+ },
+ {
+ id: 'kak',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Kakariko',
+ short: 'Kak',
+ },
+ {
+ id: 'zr',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Zora\'s River',
+ short: 'ZR',
+ },
+ {
+ id: 'kf',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Kokiri Forest',
+ short: 'KF',
+ },
+ {
+ id: 'lh',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Lake Hylia',
+ short: 'LH',
+ },
+ {
+ id: 'gv',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Gerudo Valley',
+ short: 'GV',
+ },
+ ],
+ },
+ {
+ id: 'zr',
+ bgColor: '#3c78d8',
+ fgColor: '#000000',
+ name: 'Zora\'s River',
+ short: 'ZR',
+ entrances: [
+ {
+ id: 'storms',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Storms Grotto',
+ short: 'Storms Grotto',
+ },
+ {
+ id: 'open',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Open Grotto',
+ short: 'Open Grotto',
+ },
+ {
+ id: 'boulder',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Boulder Grotto',
+ short: 'Boulder Grotto',
+ },
+ {
+ id: 'hf',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Hyrule Field',
+ short: 'HF',
+ spacer: true,
+ },
+ {
+ id: 'lw',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Lost Woods',
+ short: 'LW',
+ },
+ {
+ id: 'zd',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Zora\'s Domain',
+ short: 'ZD',
+ },
+ ],
+ },
+ {
+ id: 'zd',
+ bgColor: '#3c78d8',
+ fgColor: '#000000',
+ name: 'Zora\'s Domain',
+ short: 'ZD',
+ entrances: [
+ {
+ id: 'shop',
+ bgColor: '#aac2f1',
+ fgColor: '#000000',
+ name: 'Shop',
+ short: 'Shop',
+ },
+ {
+ id: 'storms',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Storms Grotto',
+ short: 'Storms Grotto',
+ },
+ {
+ id: 'zr',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Zora\'s River',
+ short: 'ZR',
+ },
+ {
+ id: 'lh',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Lake Hylia',
+ short: 'LH',
+ },
+ {
+ id: 'zf',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Zora\'s Fountain',
+ short: 'ZF',
+ },
+ ],
+ },
+ {
+ id: 'zf',
+ bgColor: '#3c78d8',
+ fgColor: '#000000',
+ name: 'Zora\'s Fountain',
+ short: 'ZF',
+ entrances: [
+ {
+ id: 'wall',
+ bgColor: '#aac2f1',
+ fgColor: '#000000',
+ name: 'Fairy Wall',
+ short: 'Fairy Wall',
+ },
+ {
+ id: 'jabu',
+ bgColor: '#ead1dc',
+ fgColor: '#000000',
+ name: 'Jabu Jabu\'s Belly',
+ short: 'Jabu',
+ },
+ {
+ id: 'ice',
+ bgColor: '#a64d79',
+ fgColor: '#000000',
+ name: 'Ice Cavern',
+ short: 'Ice Cavern',
+ },
+ {
+ id: 'zd',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Zora\'s Domain',
+ short: 'ZD',
+ },
+ ],
+ },
+ {
+ id: 'lh',
+ bgColor: '#4a86e8',
+ fgColor: '#000000',
+ name: 'Lake Hylia',
+ short: 'LH',
+ entrances: [
+ {
+ id: 'dive',
+ bgColor: '#cfe2f3',
+ fgColor: '#000000',
+ name: 'Lab Diving',
+ short: 'Lab Dive',
+ },
+ {
+ id: 'fishing',
+ bgColor: '#cfe2f3',
+ fgColor: '#000000',
+ name: 'Fishing Game',
+ short: 'Fishing',
+ },
+ {
+ id: 'water',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Water Temple',
+ short: 'Water Temple',
+ },
+ {
+ id: 'owl',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Owl Grotto',
+ short: 'Owl Grotto',
+ },
+ {
+ id: 'hf',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Hyrule Field',
+ short: 'HF',
+ },
+ {
+ id: 'zd',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Zora\'s Domain',
+ short: 'ZD',
+ },
+ ],
+ },
+ {
+ id: 'llr',
+ bgColor: '#f1c232',
+ fgColor: '#000000',
+ name: 'Lon Lon Ranch',
+ short: 'LLR',
+ entrances: [
+ {
+ id: 'chicken',
+ bgColor: '#ffd966',
+ fgColor: '#000000',
+ name: 'Chicken Game',
+ short: 'Chicken',
+ },
+ {
+ id: 'stable',
+ bgColor: '#ffd966',
+ fgColor: '#000000',
+ name: 'Stable',
+ short: 'Stable',
+ },
+ {
+ id: 'tower',
+ bgColor: '#ffd966',
+ fgColor: '#000000',
+ name: 'Tower',
+ short: 'Tower',
+ },
+ {
+ id: 'grotto',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Grotto',
+ short: 'Grotto',
+ },
+ {
+ id: 'hf',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Hyrule Field',
+ short: 'HF',
+ },
+ ],
+ },
+ {
+ id: 'gv',
+ bgColor: '#b45f06',
+ fgColor: '#000000',
+ name: 'Gerudo Valley',
+ short: 'GV',
+ entrances: [
+ {
+ id: 'tent',
+ bgColor: '#b45f06',
+ fgColor: '#000000',
+ name: 'Tent',
+ short: 'Tent',
+ },
+ {
+ id: 'str2',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Strength 2 Grotto',
+ short: 'Str2 Grotto',
+ },
+ {
+ id: 'storms',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Storms Grotto',
+ short: 'Storms Grotto',
+ },
+ {
+ id: 'hf',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Hyrule Field',
+ short: 'HF',
+ },
+ {
+ id: 'gf',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Gerudo Fortress',
+ short: 'GF',
+ },
+ {
+ id: 'wf',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Waterfall',
+ short: 'Waterfall',
+ oneway: true,
+ },
+ ],
+ },
+ {
+ id: 'gf',
+ bgColor: '#b45f06',
+ fgColor: '#000000',
+ name: 'Gerudo Fortress',
+ short: 'GF',
+ entrances: [
+ {
+ id: 'gtg',
+ bgColor: '#a64d79',
+ fgColor: '#000000',
+ name: 'Gerudo Training Grounds',
+ short: 'GTG',
+ },
+ {
+ id: 'storms',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Storms Grotto',
+ short: 'Storms Grotto',
+ },
+ {
+ id: 'gv',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Gerudo Valley',
+ short: 'GV',
+ },
+ {
+ id: 'hw',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Haunted Wasteland',
+ short: 'Waste',
+ },
+ ],
+ },
+ {
+ id: 'dcol',
+ bgColor: '#f1c232',
+ fgColor: '#000000',
+ name: 'Desert Colossus',
+ short: 'DCol',
+ entrances: [
+ {
+ id: 'spirit',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Spirit Temple',
+ short: 'Spirit',
+ },
+ {
+ id: 'fairy',
+ bgColor: '#ffd966',
+ fgColor: '#000000',
+ name: 'Fairy',
+ short: 'Fairy',
+ },
+ {
+ id: 'str2',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Strength 2 Grotto',
+ short: 'Str2 Grotto',
+ },
+ {
+ id: 'hw',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Haunted Wasteland',
+ short: 'Waste',
+ },
+ ],
+ },
+ {
+ id: 'hw',
+ bgColor: '#f1c232',
+ fgColor: '#000000',
+ name: 'Haunted Wasteland',
+ short: 'Waste',
+ entrances: [
+ {
+ id: 'gf',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Gerudo Fortress',
+ short: 'GF',
+ },
+ {
+ id: 'dcol',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Desert Colossus',
+ short: 'DCol',
+ },
+ ],
+ },
+ {
+ id: 'dmc',
+ bgColor: '#ff0000',
+ fgColor: '#000000',
+ name: 'Death Mountain Crater',
+ short: 'DMC',
+ entrances: [
+ {
+ id: 'fairy',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Fairy',
+ short: 'Fairy',
+ },
+ {
+ id: 'fire',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Fire Temple',
+ short: 'Fire',
+ },
+ {
+ id: 'boulder',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Boulder Grotto',
+ short: 'Boulder Gro',
+ },
+ {
+ id: 'hammer',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Hammer Grotto',
+ short: 'Hammer Gro',
+ },
+ {
+ id: 'gc',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Goron City',
+ short: 'GC',
+ },
+ {
+ id: 'dmt',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Death Mountain Trail',
+ short: 'DMT',
+ },
+ ],
+ },
+ {
+ id: 'dmt',
+ bgColor: '#ff0000',
+ fgColor: '#000000',
+ name: 'Death Mountain Trail',
+ short: 'DMT',
+ entrances: [
+ {
+ id: 'dc',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Dodongo\'s Cavern',
+ short: 'DC',
+ },
+ {
+ id: 'fairy',
+ bgColor: '#ea9999',
+ fgColor: '#000000',
+ name: 'Fairy',
+ short: 'Fairy',
+ },
+ {
+ id: 'storms',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Storms Grotto',
+ short: 'Storms Grotto',
+ },
+ {
+ id: 'cow',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Cow Grotto',
+ short: 'Cow Grotto',
+ },
+ {
+ id: 'kak',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Kakariko',
+ short: 'Kak',
+ spacer: true,
+ },
+ {
+ id: 'gc',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Goron City',
+ short: 'GC',
+ },
+ {
+ id: 'dmc',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Death Mountain Crater',
+ short: 'DMC',
+ },
+ ],
+ },
+ {
+ id: 'gc',
+ bgColor: '#ff0000',
+ fgColor: '#000000',
+ name: 'Goron City',
+ short: 'GC',
+ entrances: [
+ {
+ id: 'shop',
+ bgColor: '#ea9999',
+ fgColor: '#000000',
+ name: 'Shop',
+ short: 'Shop',
+ },
+ {
+ id: 'times',
+ bgColor: '#b7b7b7',
+ fgColor: '#000000',
+ name: 'Times Grotto',
+ short: 'Times Grotto',
+ },
+ {
+ id: 'dmt',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Death Mountain Trail',
+ short: 'DMT',
+ },
+ {
+ id: 'lw',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Lost Woods',
+ short: 'LW',
+ },
+ {
+ id: 'dmc',
+ bgColor: '#ff6d01',
+ fgColor: '#000000',
+ name: 'Death Mountain Crater',
+ short: 'DMC',
+ },
+ ],
+ },
+ {
+ id: 'tot',
+ bgColor: '#ffffff',
+ fgColor: '#000000',
+ name: 'Temple of Time',
+ short: 'ToT',
+ entrances: [
+ {
+ id: 'temple',
+ bgColor: '#b4a7d6',
+ fgColor: '#000000',
+ name: 'Temple of Time',
+ short: 'Temple',
+ },
+ {
+ id: 'm1',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Market 1',
+ short: 'M1',
+ },
+ ],
+ },
+ {
+ id: 'deku',
+ bgColor: '#ead1dc',
+ fgColor: '#000000',
+ name: 'Deku Tree',
+ short: 'Deku',
+ entrances: [
+ {
+ id: 'main',
+ bgColor: '#ead1dc',
+ fgColor: '#000000',
+ name: 'Main',
+ short: 'Main',
+ },
+ {
+ id: 'end',
+ bgColor: '#ead1dc',
+ fgColor: '#000000',
+ name: 'End',
+ short: 'End',
+ },
+ ],
+ },
+ {
+ id: 'gohma',
+ bgColor: '#ead1dc',
+ fgColor: '#000000',
+ name: 'Gohma',
+ short: 'Gohma',
+ },
+ {
+ id: 'dc',
+ bgColor: '#ead1dc',
+ fgColor: '#000000',
+ name: 'Dodongo\'s Cavern',
+ short: 'DC',
+ entrances: [
+ {
+ id: 'main',
+ bgColor: '#ead1dc',
+ fgColor: '#000000',
+ name: 'Main',
+ short: 'Main',
+ },
+ {
+ id: 'end',
+ bgColor: '#ead1dc',
+ fgColor: '#000000',
+ name: 'End',
+ short: 'End',
+ },
+ ],
+ },
+ {
+ id: 'kd',
+ bgColor: '#ead1dc',
+ fgColor: '#000000',
+ name: 'King Dodongo',
+ short: 'Dodongo',
+ },
+ {
+ id: 'jabu',
+ bgColor: '#ead1dc',
+ fgColor: '#000000',
+ name: 'Jabu Jabu\'s Belly',
+ short: 'Jabu',
+ entrances: [
+ {
+ id: 'main',
+ bgColor: '#ead1dc',
+ fgColor: '#000000',
+ name: 'Main',
+ short: 'Main',
+ },
+ {
+ id: 'end',
+ bgColor: '#ead1dc',
+ fgColor: '#000000',
+ name: 'End',
+ short: 'End',
+ },
+ ],
+ },
+ {
+ id: 'barinade',
+ bgColor: '#ead1dc',
+ fgColor: '#000000',
+ name: 'Barinade',
+ short: 'Barinade',
+ },
+ {
+ id: 'forest',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Forest Temple',
+ short: 'Forest',
+ entrances: [
+ {
+ id: 'main',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Main',
+ short: 'Main',
+ spacer: true,
+ },
+ {
+ id: 'end',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'End',
+ short: 'End',
+ spacer: true,
+ },
+ ],
+ },
+ {
+ id: 'pg',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Phantom Ganon',
+ short: 'PG',
+ spacer: true,
+ },
+ {
+ id: 'fire',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Fire Temple',
+ short: 'Fire',
+ entrances: [
+ {
+ id: 'main',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Main',
+ short: 'Main',
+ },
+ {
+ id: 'end',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'End',
+ short: 'End',
+ },
+ ],
+ },
+ {
+ id: 'volvo',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Volvagia',
+ short: 'Volvagia',
+ },
+ {
+ id: 'water',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Water Temple',
+ short: 'Water',
+ entrances: [
+ {
+ id: 'main',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Main',
+ short: 'Main',
+ },
+ {
+ id: 'end',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'End',
+ short: 'End',
+ },
+ ],
+ },
+ {
+ id: 'morpha',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Morpha',
+ short: 'Morpha',
+ },
+ {
+ id: 'shadow',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Shadow Temple',
+ short: 'Shadow',
+ entrances: [
+ {
+ id: 'main',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Main',
+ short: 'Main',
+ },
+ {
+ id: 'end',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'End',
+ short: 'End',
+ },
+ ],
+ },
+ {
+ id: 'bongo',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Bongo Bongo',
+ short: 'Bongo Bongo',
+ },
+ {
+ id: 'spirit',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Spirit Temple',
+ short: 'Spirit',
+ entrances: [
+ {
+ id: 'main',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Main',
+ short: 'Main',
+ },
+ {
+ id: 'end',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'End',
+ short: 'End',
+ },
+ ],
+ },
+ {
+ id: 'tr',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Twinrova',
+ short: 'Twinrova',
+ },
+ {
+ id: 'igc',
+ bgColor: '#d5a6bd',
+ fgColor: '#000000',
+ name: 'Inside Ganon\'s Castle',
+ short: 'IGC',
+ entrances: [
+ {
+ id: 'main',
+ bgColor: '#a64d79',
+ fgColor: '#000000',
+ name: 'Main',
+ short: 'Main',
+ spacer: true,
+ },
+ {
+ id: 'end',
+ bgColor: '#a64d79',
+ fgColor: '#000000',
+ name: 'End',
+ short: 'End',
+ spacer: true,
+ },
+ ],
+ },
+ {
+ id: 'ganon',
+ bgColor: '#a64d79',
+ fgColor: '#000000',
+ name: 'Ganon',
+ short: 'Ganon',
+ spacer: true,
+ },
+ {
+ id: 'botw',
+ bgColor: '#a64d79',
+ fgColor: '#000000',
+ name: 'Bottom of the Well',
+ short: 'Bottom Well',
+ },
+ {
+ id: 'ice',
+ bgColor: '#a64d79',
+ fgColor: '#000000',
+ name: 'Ice Cavern',
+ short: 'Ice Cavern',
+ },
+ {
+ id: 'gtg',
+ bgColor: '#a64d79',
+ fgColor: '#000000',
+ name: 'Gerudo Training Grounds',
+ short: 'GTG',
+ },
+];
+
+const DUNGEONS = [
+ {
+ id: 'd1',
+ bgColor: '#ff00ff',
+ fgColor: '#000000',
+ name: 'Dungeon Entrances',
+ short: 'Dungeon Entrances',
+ type: 'main',
+ entrances: [
+ 'deku.main',
+ 'dc.main',
+ 'jabu.main',
+ 'forest.main',
+ 'fire.main',
+ 'water.main',
+ 'shadow.main',
+ 'spirit.main',
+ 'igc.main',
+ 'botw',
+ 'ice',
+ 'gtg',
+ ],
+ },
+ {
+ id: 'd2',
+ bgColor: '#ff00ff',
+ fgColor: '#000000',
+ name: 'Dungeon Exits',
+ short: 'Dungeon Exits',
+ type: 'end',
+ entrances: [
+ 'deku.end',
+ 'dc.end',
+ 'jabu.end',
+ 'forest.end',
+ 'fire.end',
+ 'water.end',
+ 'shadow.end',
+ 'spirit.end',
+ 'igc.end',
+ ],
+ },
+ {
+ id: 'boss',
+ bgColor: '#ff00ff',
+ fgColor: '#000000',
+ name: 'Bosses',
+ short: 'Bosses',
+ entrances: [
+ 'gohma',
+ 'kd',
+ 'barinade',
+ 'pg',
+ 'volvo',
+ 'morpha',
+ 'bongo',
+ 'tr',
+ 'ganon',
+ ],
+ },
+];
+
+const ROOMS = [
+ {
+ id: 'trash',
+ bgColor: '#333333',
+ fgColor: '#dddddd',
+ name: 'Trash',
+ short: 'Trash',
+ multi: true,
+ },
+ {
+ id: 'zlf',
+ bgColor: '#fffd00',
+ fgColor: '#000000',
+ name: 'ZL Fairy',
+ short: 'ZL Fairy',
+ multi: true,
+ },
+ {
+ id: 'toti',
+ bgColor: '#ff0000',
+ fgColor: '#000000',
+ name: 'Temple of Time',
+ short: 'Temple of Time',
+ },
+ {
+ id: 'bcb',
+ bgColor: '#fffd00',
+ fgColor: '#000000',
+ name: 'Bombchu Bowling',
+ short: 'Bombchu Bow',
+ },
+ {
+ id: 'fish',
+ bgColor: '#fffd00',
+ fgColor: '#000000',
+ name: 'Fishing Game',
+ short: 'Fishing',
+ },
+ {
+ id: 'sling',
+ bgColor: '#fffd00',
+ fgColor: '#000000',
+ name: 'Slingshot Game',
+ short: 'Slingshot Game',
+ },
+ {
+ id: 'arch',
+ bgColor: '#fffd00',
+ fgColor: '#000000',
+ name: 'Archery Game',
+ short: 'Archery Game',
+ },
+ {
+ id: 'tow',
+ bgColor: '#fffd00',
+ fgColor: '#000000',
+ name: 'Lon Lon Ranch Tower',
+ short: 'Ranch Tower',
+ },
+ {
+ id: 'chick',
+ bgColor: '#fffd00',
+ fgColor: '#000000',
+ name: 'Chicken Game',
+ short: 'Chicken Game',
+ },
+ {
+ id: 'mill',
+ bgColor: '#fffd00',
+ fgColor: '#000000',
+ name: 'Windmill',
+ short: 'Windmill',
+ },
+ {
+ id: 'tomb',
+ bgColor: '#fffd00',
+ fgColor: '#000000',
+ name: 'Family Tomb',
+ short: 'Family Tomb',
+ },
+ {
+ id: 'ssg',
+ bgColor: '#fffd00',
+ fgColor: '#000000',
+ name: 'Sun Song Grave',
+ short: 'Sun Song Grave',
+ },
+ {
+ id: 'mask',
+ bgColor: '#fffd00',
+ fgColor: '#000000',
+ name: 'Mask Shop',
+ short: 'Mask Shop',
+ },
+ {
+ id: 'poe',
+ bgColor: '#fffd00',
+ fgColor: '#000000',
+ name: 'Big Poe',
+ short: 'Big Poe',
+ },
+ {
+ id: 'thtr',
+ bgColor: '#fffd00',
+ fgColor: '#000000',
+ name: 'Mask Theater',
+ short: 'Mask Theater',
+ },
+ {
+ id: 'skull',
+ bgColor: '#fffd00',
+ fgColor: '#000000',
+ name: 'Skulltula House',
+ short: 'Skulltula House',
+ },
+ {
+ id: 'tcg',
+ bgColor: '#fffd00',
+ fgColor: '#000000',
+ name: 'Treasute Chest Game',
+ short: 'TCG',
+ },
+ {
+ id: 'lab',
+ bgColor: '#fffd00',
+ fgColor: '#000000',
+ name: 'Lab Diving',
+ short: 'Lab Dive',
+ },
+ {
+ id: 'tek',
+ bgColor: '#fffd00',
+ fgColor: '#000000',
+ name: 'Tektite Grotto',
+ short: 'Tektite',
+ },
+];
+
+const CONTEXT = React.createContext({});
+
+const useTracker = () => React.useContext(CONTEXT);
+
+const mapEntrance = (area, entrance) => ({
+ ...entrance,
+ id: `${area.id}.${entrance.id}`,
+ area,
+});
+
+const getArea = (id) => {
+ return AREAS.find((area) => area.id === id);
+};
+
+const getEntranceOfArea = (area, entranceId) => {
+ if (!area) return null;
+ if (!area.entrances) return null;
+ const entrance = area.entrances.find((entrance) => entrance.id === entranceId);
+ return mapEntrance(area, entrance);
+};
+
+const getEntrance = (id) => {
+ if (!id) return null;
+ const dotPos = id.indexOf('.');
+ if (dotPos === -1) {
+ return getArea(id);
+ }
+ const areaId = id.substring(0, dotPos);
+ const entranceId = id.substring(dotPos + 1);
+ const area = getArea(areaId);
+ const entrance = getEntranceOfArea(area, entranceId);
+ return entrance;
+};
+
+const getRoom = (id) => {
+ return ROOMS.find((room) => room.id === id);
+};
+
+const entranceShort = (entrance) => {
+ if (!entrance) return null;
+ return entrance.area
+ ? `${entrance.area.short} (${entrance.short})`
+ : entrance.short;
+};
+
+const entranceName = (entrance) => {
+ if (!entrance) return null;
+ return entrance.area
+ ? `[${entrance.area.short}] ${entrance.name}`
+ : entrance.name;
+};
+
+const entranceFull = (entrance) => {
+ if (!entrance) return null;
+ return entrance.area
+ ? `${entrance.area.name} - ${entrance.name}`
+ : entrance.name;
+};
+
+const entranceStyle = (entrance) => {
+ if (!entrance) return null;
+ return {
+ backgroundColor: entrance.bgColor,
+ color: entrance.fgColor,
+ };
+};
+
+const SelectBox = ({ id, name, onChange, options, value }) => {
+ const [open, setOpen] = React.useState(false);
+ const [search, setSearch] = React.useState('');
+
+ const ref = React.useRef();
+ const searchRef = React.useRef();
+
+ const valueEntrance = React.useMemo(() => getEntrance(value) || getRoom(value), [value]);
+
+ const searcher = React.useMemo(() => {
+ return new FuzzySearch(options, ['id', 'name', 'short'], { sort: true });
+ }, [options]);
+
+ const results = React.useMemo(() => {
+ return searcher.search(search);
+ }, [search, searcher]);
+
+ React.useEffect(() => {
+ const handleEventOutside = e => {
+ if (ref.current && !ref.current.contains(e.target)) {
+ setOpen(false);
+ }
+ };
+ document.addEventListener('mousedown', handleEventOutside, true);
+ document.addEventListener('focus', handleEventOutside, true);
+ return () => {
+ document.removeEventListener('mousedown', handleEventOutside, true);
+ document.removeEventListener('focus', handleEventOutside, true);
+ };
+ }, []);
+
+ const classNames = ['entrance-select'];
+ if (open) classNames.push('is-open');
+
+ return <div className={classNames.join(' ')} ref={ref}>
+ <input
+ className="entrance-search"
+ id={id}
+ onChange={({ target: { value } }) => setSearch(value)}
+ onFocus={() => setOpen(true)}
+ ref={searchRef}
+ type="search"
+ value={search}
+ />
+ <div
+ aria-controls={`${id}.options`}
+ aria-expanded={open ? 'true' : 'false'}
+ aria-haspopup={`${id}.options`}
+ className="entrance-value"
+ onClick={() => {
+ setOpen(true);
+ searchRef.current.focus();
+ searchRef.current.select();
+ }}
+ onContextMenu={(e) => {
+ if (value) {
+ onChange({ target: { name, value: null } });
+ } else {
+ onChange({ target: { name, value: 'trash' } });
+ setSearch('');
+ }
+ e.preventDefault();
+ e.stopPropagation();
+ }}
+ role="combobox"
+ style={entranceStyle(valueEntrance)}
+ title={entranceFull(valueEntrance)}
+ >
+ {entranceShort(valueEntrance)}
+ </div>
+ <div className="entrance-options" id={`${id}.options`} role="listbox">
+ {results.map((entrance) =>
+ <div
+ className="entrance-option"
+ key={entrance.id}
+ onClick={() => {
+ onChange({ target: { name, value: entrance.id } });
+ setOpen(false);
+ setSearch('');
+ }}
+ role="option"
+ style={entranceStyle(entrance)}
+ >
+ {entranceName(entrance)}
+ </div>
+ )}
+ </div>
+ </div>;
+};
+
+SelectBox.propTypes = {
+ className: PropTypes.string,
+ id: PropTypes.string,
+ name: PropTypes.string,
+ onChange: PropTypes.func,
+ options: PropTypes.arrayOf(PropTypes.shape({
+ id: PropTypes.string,
+ name: PropTypes.string,
+ })),
+ value: PropTypes.string,
+};
+
+const EntranceGroup = ({ checked = 0, children, group, total = 0 }) => {
+ return <div className="entrance-group">
+ <h2 style={entranceStyle(group)}>
+ {entranceName(group)}
+ {checked && checked !== total ?
+ <span className="checks">{checked}/{total}</span>
+ : null}
+ </h2>
+ {children}
+ </div>;
+};
+
+EntranceGroup.propTypes = {
+ checked: PropTypes.number,
+ children: PropTypes.node,
+ group: PropTypes.shape({
+ bgColor: PropTypes.string,
+ fgColor: PropTypes.string,
+ name: PropTypes.string,
+ }),
+ total: PropTypes.number,
+};
+
+const EntranceRow = ({ entranceId }) => {
+ const entrance = React.useMemo(() => getEntrance(entranceId), [entranceId]);
+
+ if (!entrance) {
+ return <div className="entrance-row empty" />;
+ }
+
+ const { connections, freeEntrances, setConnection } = useTracker();
+
+ const classNames = ['entrance-row'];
+ if (entrance.spacer) classNames.push('mt-2');
+ if (connections[entrance.id] === 'trash') classNames.push('is-trash');
+
+ return <div className={classNames.join(' ')}>
+ <label
+ className="entrance-label"
+ htmlFor={entranceId}
+ style={entranceStyle(entrance)}
+ title={entranceFull(entrance)}
+ >
+ {entranceShort(entrance)}
+ </label>
+ <SelectBox
+ id={entranceId}
+ name={entranceId}
+ onChange={({ target: { name, value } }) => setConnection(name, value)}
+ options={freeEntrances}
+ value={connections[entranceId]}
+ />
+ </div>;
+};
+
+EntranceRow.propTypes = {
+ entranceId: PropTypes.string,
+};
+
+const MixedPoolsTracker = () => {
+ const [connections, setConnections] = React.useState({});
+
+ const setConnection = React.useCallback((src, dst) => {
+ setConnections((c) => {
+ const newConn = { ...c };
+ if (getEntrance(c[src])) {
+ // unset old connection
+ newConn[c[src]] = null;
+ }
+ newConn[src] = dst;
+ if (dst && getEntrance(src)) {
+ newConn[dst] = src;
+ }
+ return newConn;
+ });
+ }, []);
+
+ const entrances = React.useMemo(() => {
+ const options = [];
+ ROOMS.forEach((room) => {
+ options.push(room);
+ });
+ AREAS.forEach((area) => {
+ if (area.entrances) {
+ area.entrances.forEach((entrance) => {
+ if (entrance.oneway) return;
+ options.push(getEntranceOfArea(area, entrance.id));
+ });
+ } else {
+ options.push(getEntrance(area.id));
+ }
+ });
+ return options;
+ }, []);
+
+ const freeEntrances = React.useMemo(() => {
+ return entrances.filter((entrance) => {
+ return entrance.multi ||
+ !Object.entries(connections).find(([, b]) => b === entrance.id);
+ });
+ }, [connections, entrances]);
+
+ const context = React.useMemo(() => ({
+ connections, entrances, freeEntrances, setConnection,
+ }), [connections, entrances, freeEntrances, setConnection]);
+
+ const superGroups = React.useMemo(() => {
+ const sg = [
+ {
+ key: 'one',
+ groups: ['kf', 'lw', 'sfm', 'gy'],
+ },
+ {
+ key: 'two',
+ groups: ['kak', 'm1', 'm2', 'hc'],
+ },
+ {
+ key: 'three',
+ groups: ['hf', 'zr', 'zd', 'zf'],
+ },
+ {
+ key: 'four',
+ groups: ['lh', 'llr', 'gv', 'gf', 'dcol', 'hw'],
+ },
+ {
+ key: 'five',
+ groups: ['dmc', 'dmt', 'gc', 'tot'],
+ },
+ ];
+ sg.forEach((superGroup) => {
+ superGroup.groups = superGroup.groups.map((areaId) => {
+ const area = getArea(areaId);
+ const entranceIds = area.entrances.map((entrance) => `${area.id}.${entrance.id}`);
+ const checked = entranceIds.filter((entranceId) =>
+ Object.entries(connections).find(([a, b]) => b && a === entranceId)
+ ).length;
+ return {
+ area,
+ entranceIds,
+ checked,
+ total: area.entrances.length,
+ };
+ });
+ });
+ return sg;
+ }, [connections]);
+
+ return <CONTEXT.Provider value={context}>
+ <div className="mixed-pools-tracker">
+ <div className="columns">
+ {superGroups.map((sg) =>
+ <div className="column" key={sg.key}>
+ {sg.groups.map(group =>
+ <EntranceGroup
+ checked={group.checked}
+ group={group.area}
+ key={group.area.id}
+ total={group.total}
+ >
+ {group.entranceIds.map((entranceId) =>
+ <EntranceRow entranceId={entranceId} key={entranceId} />
+ )}
+ </EntranceGroup>
+ )}
+ </div>
+ )}
+ </div>
+ <div className="columns">
+ {DUNGEONS.map((area) =>
+ <div className="column" key={area.id}>
+ <EntranceGroup group={area}>
+ {area.entrances.map((entranceId) =>
+ <EntranceRow
+ entranceId={entranceId}
+ key={entranceId}
+ />
+ )}
+ </EntranceGroup>
+ </div>
+ )}
+ </div>
+ </div>
+ </CONTEXT.Provider>;
+};
+
+export default MixedPoolsTracker;