589 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			589 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| window.addEventListener('load', () => {
 | |
|   fetchSettingData().then((results) => {
 | |
|     let settingHash = localStorage.getItem('weighted-settings-hash');
 | |
|     if (!settingHash) {
 | |
|       // If no hash data has been set before, set it now
 | |
|       localStorage.setItem('weighted-settings-hash', md5(results));
 | |
|       localStorage.removeItem('weighted-settings');
 | |
|       settingHash = md5(results);
 | |
|     }
 | |
| 
 | |
|     if (settingHash !== md5(results)) {
 | |
|       const userMessage = document.getElementById('user-message');
 | |
|       userMessage.innerText = "Your settings are out of date! Click here to update them! Be aware this will reset " +
 | |
|         "them all to default.";
 | |
|       userMessage.style.display = "block";
 | |
|       userMessage.addEventListener('click', resetSettings);
 | |
|     }
 | |
| 
 | |
|     // Page setup
 | |
|     createDefaultSettings(results);
 | |
|     buildUI(results);
 | |
|     updateVisibleGames();
 | |
|     adjustHeaderWidth();
 | |
| 
 | |
|     // Event listeners
 | |
|     document.getElementById('export-settings').addEventListener('click', () => exportSettings());
 | |
|     document.getElementById('generate-race').addEventListener('click', () => generateGame(true));
 | |
|     document.getElementById('generate-game').addEventListener('click', () => generateGame());
 | |
| 
 | |
|     // Name input field
 | |
|     const weightedSettings = JSON.parse(localStorage.getItem('weighted-settings'));
 | |
|     const nameInput = document.getElementById('player-name');
 | |
|     nameInput.setAttribute('data-type', 'data');
 | |
|     nameInput.setAttribute('data-setting', 'name');
 | |
|     nameInput.addEventListener('keyup', updateBaseSetting);
 | |
|     nameInput.value = weightedSettings.name;
 | |
|   });
 | |
| });
 | |
| 
 | |
| const resetSettings = () => {
 | |
|   localStorage.removeItem('weighted-settings');
 | |
|   localStorage.removeItem('weighted-settings-hash')
 | |
|   window.location.reload();
 | |
| };
 | |
| 
 | |
| const fetchSettingData = () => new Promise((resolve, reject) => {
 | |
|   fetch(new Request(`${window.location.origin}/static/generated/weighted-settings.json`)).then((response) => {
 | |
|     try{ resolve(response.json()); }
 | |
|     catch(error){ reject(error); }
 | |
|   });
 | |
| });
 | |
| 
 | |
| const createDefaultSettings = (settingData) => {
 | |
|   if (!localStorage.getItem('weighted-settings')) {
 | |
|     const newSettings = {};
 | |
| 
 | |
|     // Transfer base options directly
 | |
|     for (let baseOption of Object.keys(settingData.baseOptions)){
 | |
|       newSettings[baseOption] = settingData.baseOptions[baseOption];
 | |
|     }
 | |
| 
 | |
|     // Set options per game
 | |
|     for (let game of Object.keys(settingData.games)) {
 | |
|       // Initialize game object
 | |
|       newSettings[game] = {};
 | |
| 
 | |
|       // Transfer game settings
 | |
|       for (let gameSetting of Object.keys(settingData.games[game].gameSettings)){
 | |
|         newSettings[game][gameSetting] = {};
 | |
| 
 | |
|         const setting = settingData.games[game].gameSettings[gameSetting];
 | |
|         switch(setting.type){
 | |
|           case 'select':
 | |
|             setting.options.forEach((option) => {
 | |
|               newSettings[game][gameSetting][option.value] =
 | |
|                 (setting.hasOwnProperty('defaultValue') && setting.defaultValue === option.value) ? 25 : 0;
 | |
|             });
 | |
|             break;
 | |
|           case 'range':
 | |
|             for (let i = setting.min; i <= setting.max; ++i){
 | |
|               newSettings[game][gameSetting][i] =
 | |
|                 (setting.hasOwnProperty('defaultValue') && setting.defaultValue === i) ? 25 : 0;
 | |
|             }
 | |
|             newSettings[game][gameSetting]['random'] = 0;
 | |
|             newSettings[game][gameSetting]['random-low'] = 0;
 | |
|             newSettings[game][gameSetting]['random-high'] = 0;
 | |
|             break;
 | |
|           default:
 | |
|             console.error(`Unknown setting type for ${game} setting ${gameSetting}: ${setting.type}`);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       newSettings[game].start_inventory = [];
 | |
|       newSettings[game].exclude_locations = [];
 | |
|       newSettings[game].local_items = [];
 | |
|       newSettings[game].non_local_items = [];
 | |
|       newSettings[game].start_hints = [];
 | |
|     }
 | |
| 
 | |
|     localStorage.setItem('weighted-settings', JSON.stringify(newSettings));
 | |
|   }
 | |
| };
 | |
| 
 | |
| // TODO: Include item configs: start_inventory, local_items, non_local_items, start_hints
 | |
| // TODO: Include location configs: exclude_locations
 | |
| const buildUI = (settingData) => {
 | |
|   // Build the game-choice div
 | |
|   buildGameChoice(settingData.games);
 | |
| 
 | |
|   const gamesWrapper = document.getElementById('games-wrapper');
 | |
|   Object.keys(settingData.games).forEach((game) => {
 | |
|     // Create game div, invisible by default
 | |
|     const gameDiv = document.createElement('div');
 | |
|     gameDiv.setAttribute('id', `${game}-div`);
 | |
|     gameDiv.classList.add('game-div');
 | |
|     gameDiv.classList.add('invisible');
 | |
| 
 | |
|     const gameHeader = document.createElement('h2');
 | |
|     gameHeader.innerText = game;
 | |
|     gameDiv.appendChild(gameHeader);
 | |
| 
 | |
|     const collapseButton = document.createElement('a');
 | |
|     collapseButton.innerText = '(Collapse)';
 | |
|     gameDiv.appendChild(collapseButton);
 | |
| 
 | |
|     const expandButton = document.createElement('a');
 | |
|     expandButton.innerText = '(Expand)';
 | |
|     expandButton.classList.add('invisible');
 | |
|     gameDiv.appendChild(expandButton);
 | |
| 
 | |
|     const optionsDiv = buildOptionsDiv(game, settingData.games[game].gameSettings);
 | |
|     gameDiv.appendChild(optionsDiv);
 | |
|     gamesWrapper.appendChild(gameDiv);
 | |
| 
 | |
|     collapseButton.addEventListener('click', () => {
 | |
|       collapseButton.classList.add('invisible');
 | |
|       optionsDiv.classList.add('invisible');
 | |
|       expandButton.classList.remove('invisible');
 | |
|     });
 | |
| 
 | |
|     expandButton.addEventListener('click', () => {
 | |
|       collapseButton.classList.remove('invisible');
 | |
|       optionsDiv.classList.remove('invisible');
 | |
|       expandButton.classList.add('invisible');
 | |
|     });
 | |
|   });
 | |
| };
 | |
| 
 | |
| const buildGameChoice = (games) => {
 | |
|   const settings = JSON.parse(localStorage.getItem('weighted-settings'));
 | |
|   const gameChoiceDiv = document.getElementById('game-choice');
 | |
|   const h2 = document.createElement('h2');
 | |
|   h2.innerText = 'Game Select';
 | |
|   gameChoiceDiv.appendChild(h2);
 | |
| 
 | |
|   const gameSelectDescription = document.createElement('p');
 | |
|   gameSelectDescription.classList.add('setting-description');
 | |
|   gameSelectDescription.innerText = 'Choose which games you might be required to play.';
 | |
|   gameChoiceDiv.appendChild(gameSelectDescription);
 | |
| 
 | |
|   const hintText = document.createElement('p');
 | |
|   hintText.classList.add('hint-text');
 | |
|   hintText.innerText = 'If a game\'s value is greater than zero, you can click it\'s name to jump ' +
 | |
|     'to that section.'
 | |
|   gameChoiceDiv.appendChild(hintText);
 | |
| 
 | |
|   // Build the game choice table
 | |
|   const table = document.createElement('table');
 | |
|   const tbody = document.createElement('tbody');
 | |
| 
 | |
|   Object.keys(games).forEach((game) => {
 | |
|     const tr = document.createElement('tr');
 | |
|     const tdLeft = document.createElement('td');
 | |
|     tdLeft.classList.add('td-left');
 | |
|     const span = document.createElement('span');
 | |
|     span.innerText = game;
 | |
|     span.setAttribute('id', `${game}-game-option`)
 | |
|     tdLeft.appendChild(span);
 | |
|     tr.appendChild(tdLeft);
 | |
| 
 | |
|     const tdMiddle = document.createElement('td');
 | |
|     tdMiddle.classList.add('td-middle');
 | |
|     const range = document.createElement('input');
 | |
|     range.setAttribute('type', 'range');
 | |
|     range.setAttribute('min', 0);
 | |
|     range.setAttribute('max', 50);
 | |
|     range.setAttribute('data-type', 'weight');
 | |
|     range.setAttribute('data-setting', 'game');
 | |
|     range.setAttribute('data-option', game);
 | |
|     range.value = settings.game[game];
 | |
|     range.addEventListener('change', (evt) => {
 | |
|       updateBaseSetting(evt);
 | |
|       updateVisibleGames(); // Show or hide games based on the new settings
 | |
|     });
 | |
|     tdMiddle.appendChild(range);
 | |
|     tr.appendChild(tdMiddle);
 | |
| 
 | |
|     const tdRight = document.createElement('td');
 | |
|     tdRight.setAttribute('id', `game-${game}`)
 | |
|     tdRight.classList.add('td-right');
 | |
|     tdRight.innerText = range.value;
 | |
|     tr.appendChild(tdRight);
 | |
|     tbody.appendChild(tr);
 | |
|   });
 | |
| 
 | |
|   table.appendChild(tbody);
 | |
|   gameChoiceDiv.appendChild(table);
 | |
| };
 | |
| 
 | |
| const buildOptionsDiv = (game, settings) => {
 | |
|   const currentSettings = JSON.parse(localStorage.getItem('weighted-settings'));
 | |
|   const optionsWrapper = document.createElement('div');
 | |
|   optionsWrapper.classList.add('settings-wrapper');
 | |
| 
 | |
|   Object.keys(settings).forEach((settingName) => {
 | |
|     const setting = settings[settingName];
 | |
|     const settingWrapper = document.createElement('div');
 | |
|     settingWrapper.classList.add('setting-wrapper');
 | |
| 
 | |
|     const settingNameHeader = document.createElement('h4');
 | |
|     settingNameHeader.innerText = setting.displayName;
 | |
|     settingWrapper.appendChild(settingNameHeader);
 | |
| 
 | |
|     const settingDescription = document.createElement('p');
 | |
|     settingDescription.classList.add('setting-description');
 | |
|     settingDescription.innerText = setting.description.replace(/(\n)/g, ' ');
 | |
|     settingWrapper.appendChild(settingDescription);
 | |
| 
 | |
|     switch(setting.type){
 | |
|       case 'select':
 | |
|         const optionTable = document.createElement('table');
 | |
|         const tbody = document.createElement('tbody');
 | |
| 
 | |
|         // Add a weight range for each option
 | |
|         setting.options.forEach((option) => {
 | |
|           const tr = document.createElement('tr');
 | |
|           const tdLeft = document.createElement('td');
 | |
|           tdLeft.classList.add('td-left');
 | |
|           tdLeft.innerText = option.name;
 | |
|           tr.appendChild(tdLeft);
 | |
| 
 | |
|           const tdMiddle = document.createElement('td');
 | |
|           tdMiddle.classList.add('td-middle');
 | |
|           const range = document.createElement('input');
 | |
|           range.setAttribute('type', 'range');
 | |
|           range.setAttribute('data-game', game);
 | |
|           range.setAttribute('data-setting', settingName);
 | |
|           range.setAttribute('data-option', option.value);
 | |
|           range.setAttribute('data-type', setting.type);
 | |
|           range.setAttribute('min', 0);
 | |
|           range.setAttribute('max', 50);
 | |
|           range.addEventListener('change', updateGameSetting);
 | |
|           range.value = currentSettings[game][settingName][option.value];
 | |
|           tdMiddle.appendChild(range);
 | |
|           tr.appendChild(tdMiddle);
 | |
| 
 | |
|           const tdRight = document.createElement('td');
 | |
|           tdRight.setAttribute('id', `${game}-${settingName}-${option.value}`)
 | |
|           tdRight.classList.add('td-right');
 | |
|           tdRight.innerText = range.value;
 | |
|           tr.appendChild(tdRight);
 | |
| 
 | |
|           tbody.appendChild(tr);
 | |
|         });
 | |
| 
 | |
|         optionTable.appendChild(tbody);
 | |
|         settingWrapper.appendChild(optionTable);
 | |
|         break;
 | |
| 
 | |
|       case 'range':
 | |
|         const hintText = document.createElement('p');
 | |
|         hintText.classList.add('hint-text');
 | |
|         hintText.innerHTML = 'This is a range option. You may enter valid numerical values in the text box below, ' +
 | |
|           `then press the "Add" button to add a weight for it.<br />Minimum value: ${setting.min}<br />` +
 | |
|           `Maximum value: ${setting.max}`;
 | |
|         settingWrapper.appendChild(hintText);
 | |
| 
 | |
|         const addOptionDiv = document.createElement('div');
 | |
|         addOptionDiv.classList.add('add-option-div');
 | |
|         const optionInput = document.createElement('input');
 | |
|         optionInput.setAttribute('id', `${game}-${settingName}-option`);
 | |
|         optionInput.setAttribute('placeholder', `${setting.min} - ${setting.max}`);
 | |
|         addOptionDiv.appendChild(optionInput);
 | |
|         const addOptionButton = document.createElement('button');
 | |
|         addOptionButton.innerText = 'Add';
 | |
|         addOptionDiv.appendChild(addOptionButton);
 | |
|         settingWrapper.appendChild(addOptionDiv);
 | |
|         optionInput.addEventListener('keydown', (evt) => {
 | |
|           if (evt.key === 'Enter') { addOptionButton.dispatchEvent(new Event('click')); }
 | |
|         });
 | |
| 
 | |
|         const rangeTable = document.createElement('table');
 | |
|         const rangeTbody = document.createElement('tbody');
 | |
| 
 | |
|         if (((setting.max - setting.min) + 1) < 11) {
 | |
|           for (let i=setting.min; i <= setting.max; ++i) {
 | |
|             const tr = document.createElement('tr');
 | |
|               const tdLeft = document.createElement('td');
 | |
|               tdLeft.classList.add('td-left');
 | |
|               tdLeft.innerText = i;
 | |
|               tr.appendChild(tdLeft);
 | |
| 
 | |
|               const tdMiddle = document.createElement('td');
 | |
|               tdMiddle.classList.add('td-middle');
 | |
|               const range = document.createElement('input');
 | |
|               range.setAttribute('type', 'range');
 | |
|               range.setAttribute('id', `${game}-${settingName}-${i}-range`);
 | |
|               range.setAttribute('data-game', game);
 | |
|               range.setAttribute('data-setting', settingName);
 | |
|               range.setAttribute('data-option', i);
 | |
|               range.setAttribute('min', 0);
 | |
|               range.setAttribute('max', 50);
 | |
|               range.addEventListener('change', updateGameSetting);
 | |
|               range.value = currentSettings[game][settingName][i];
 | |
|               tdMiddle.appendChild(range);
 | |
|               tr.appendChild(tdMiddle);
 | |
| 
 | |
|               const tdRight = document.createElement('td');
 | |
|               tdRight.setAttribute('id', `${game}-${settingName}-${i}`)
 | |
|               tdRight.classList.add('td-right');
 | |
|               tdRight.innerText = range.value;
 | |
|               tr.appendChild(tdRight);
 | |
| 
 | |
|               rangeTbody.appendChild(tr);
 | |
|           }
 | |
|         } else {
 | |
|           Object.keys(currentSettings[game][settingName]).forEach((option) => {
 | |
|             if (currentSettings[game][settingName][option] > 0) {
 | |
|               const tr = document.createElement('tr');
 | |
|               const tdLeft = document.createElement('td');
 | |
|               tdLeft.classList.add('td-left');
 | |
|               tdLeft.innerText = option;
 | |
|               tr.appendChild(tdLeft);
 | |
| 
 | |
|               const tdMiddle = document.createElement('td');
 | |
|               tdMiddle.classList.add('td-middle');
 | |
|               const range = document.createElement('input');
 | |
|               range.setAttribute('type', 'range');
 | |
|               range.setAttribute('id', `${game}-${settingName}-${option}-range`);
 | |
|               range.setAttribute('data-game', game);
 | |
|               range.setAttribute('data-setting', settingName);
 | |
|               range.setAttribute('data-option', option);
 | |
|               range.setAttribute('min', 0);
 | |
|               range.setAttribute('max', 50);
 | |
|               range.addEventListener('change', updateGameSetting);
 | |
|               range.value = currentSettings[game][settingName][parseInt(option, 10)];
 | |
|               tdMiddle.appendChild(range);
 | |
|               tr.appendChild(tdMiddle);
 | |
| 
 | |
|               const tdRight = document.createElement('td');
 | |
|               tdRight.setAttribute('id', `${game}-${settingName}-${option}`)
 | |
|               tdRight.classList.add('td-right');
 | |
|               tdRight.innerText = range.value;
 | |
|               tr.appendChild(tdRight);
 | |
| 
 | |
|               const tdDelete = document.createElement('td');
 | |
|               tdDelete.classList.add('td-delete');
 | |
|               const deleteButton = document.createElement('span');
 | |
|               deleteButton.classList.add('range-option-delete');
 | |
|               deleteButton.innerText = '❌';
 | |
|               deleteButton.addEventListener('click', () => {
 | |
|                 range.value = 0;
 | |
|                 range.dispatchEvent(new Event('change'));
 | |
|                 rangeTbody.removeChild(tr);
 | |
|               });
 | |
|               tdDelete.appendChild(deleteButton);
 | |
|               tr.appendChild(tdDelete);
 | |
| 
 | |
|               rangeTbody.appendChild(tr);
 | |
|             }
 | |
|           });
 | |
|         }
 | |
| 
 | |
|         ['random', 'random-low', 'random-high'].forEach((option) => {
 | |
|           const tr = document.createElement('tr');
 | |
|             const tdLeft = document.createElement('td');
 | |
|             tdLeft.classList.add('td-left');
 | |
|             tdLeft.innerText = option;
 | |
|             tr.appendChild(tdLeft);
 | |
| 
 | |
|             const tdMiddle = document.createElement('td');
 | |
|             tdMiddle.classList.add('td-middle');
 | |
|             const range = document.createElement('input');
 | |
|             range.setAttribute('type', 'range');
 | |
|             range.setAttribute('id', `${game}-${settingName}-${option}-range`);
 | |
|             range.setAttribute('data-game', game);
 | |
|             range.setAttribute('data-setting', settingName);
 | |
|             range.setAttribute('data-option', option);
 | |
|             range.setAttribute('min', 0);
 | |
|             range.setAttribute('max', 50);
 | |
|             range.addEventListener('change', updateGameSetting);
 | |
|             range.value = currentSettings[game][settingName][option];
 | |
|             tdMiddle.appendChild(range);
 | |
|             tr.appendChild(tdMiddle);
 | |
| 
 | |
|             const tdRight = document.createElement('td');
 | |
|             tdRight.setAttribute('id', `${game}-${settingName}-${option}`)
 | |
|             tdRight.classList.add('td-right');
 | |
|             tdRight.innerText = range.value;
 | |
|             tr.appendChild(tdRight);
 | |
|             rangeTbody.appendChild(tr);
 | |
|         });
 | |
| 
 | |
|         rangeTable.appendChild(rangeTbody);
 | |
|         settingWrapper.appendChild(rangeTable);
 | |
| 
 | |
|         addOptionButton.addEventListener('click', () => {
 | |
|           const optionInput = document.getElementById(`${game}-${settingName}-option`);
 | |
|           let option = optionInput.value;
 | |
|           if (!option || !option.trim()) { return; }
 | |
|           option = parseInt(option, 10);
 | |
|           if ((option < setting.min) || (option > setting.max)) { return; }
 | |
|           optionInput.value = '';
 | |
|           if (document.getElementById(`${game}-${settingName}-${option}-range`)) { return; }
 | |
| 
 | |
|           const tr = document.createElement('tr');
 | |
|           const tdLeft = document.createElement('td');
 | |
|           tdLeft.classList.add('td-left');
 | |
|           tdLeft.innerText = option;
 | |
|           tr.appendChild(tdLeft);
 | |
| 
 | |
|           const tdMiddle = document.createElement('td');
 | |
|           tdMiddle.classList.add('td-middle');
 | |
|           const range = document.createElement('input');
 | |
|           range.setAttribute('type', 'range');
 | |
|           range.setAttribute('id', `${game}-${settingName}-${option}-range`);
 | |
|           range.setAttribute('data-game', game);
 | |
|           range.setAttribute('data-setting', settingName);
 | |
|           range.setAttribute('data-option', option);
 | |
|           range.setAttribute('min', 0);
 | |
|           range.setAttribute('max', 50);
 | |
|           range.addEventListener('change', updateGameSetting);
 | |
|           range.value = currentSettings[game][settingName][parseInt(option, 10)];
 | |
|           tdMiddle.appendChild(range);
 | |
|           tr.appendChild(tdMiddle);
 | |
| 
 | |
|           const tdRight = document.createElement('td');
 | |
|           tdRight.setAttribute('id', `${game}-${settingName}-${option}`)
 | |
|           tdRight.classList.add('td-right');
 | |
|           tdRight.innerText = range.value;
 | |
|           tr.appendChild(tdRight);
 | |
| 
 | |
|           const tdDelete = document.createElement('td');
 | |
|           tdDelete.classList.add('td-delete');
 | |
|           const deleteButton = document.createElement('span');
 | |
|           deleteButton.classList.add('range-option-delete');
 | |
|           deleteButton.innerText = '❌';
 | |
|           deleteButton.addEventListener('click', () => {
 | |
|             range.value = 0;
 | |
|             range.dispatchEvent(new Event('change'));
 | |
|             rangeTbody.removeChild(tr);
 | |
|           });
 | |
|           tdDelete.appendChild(deleteButton);
 | |
|           tr.appendChild(tdDelete);
 | |
| 
 | |
|           rangeTbody.appendChild(tr);
 | |
|         });
 | |
|         break;
 | |
| 
 | |
|       default:
 | |
|         console.error(`Unknown setting type for ${game} setting ${setting}: ${settings[setting].type}`);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     optionsWrapper.appendChild(settingWrapper);
 | |
|   });
 | |
| 
 | |
|   return optionsWrapper;
 | |
| };
 | |
| 
 | |
| const updateVisibleGames = () => {
 | |
|   const settings = JSON.parse(localStorage.getItem('weighted-settings'));
 | |
|   Object.keys(settings.game).forEach((game) => {
 | |
|     const gameDiv = document.getElementById(`${game}-div`);
 | |
|     const gameOption = document.getElementById(`${game}-game-option`);
 | |
|     if (parseInt(settings.game[game], 10) > 0) {
 | |
|       gameDiv.classList.remove('invisible');
 | |
|       gameOption.classList.add('jump-link');
 | |
|       gameOption.addEventListener('click', () => {
 | |
|         const gameDiv = document.getElementById(`${game}-div`);
 | |
|         if (gameDiv.classList.contains('invisible')) { return; }
 | |
|         gameDiv.scrollIntoView({
 | |
|           behavior: 'smooth',
 | |
|           block: 'start',
 | |
|         });
 | |
|       });
 | |
|     } else {
 | |
|       gameDiv.classList.add('invisible');
 | |
|       gameOption.classList.remove('jump-link');
 | |
| 
 | |
|     }
 | |
|   });
 | |
| };
 | |
| 
 | |
| const updateBaseSetting = (event) => {
 | |
|   const settings = JSON.parse(localStorage.getItem('weighted-settings'));
 | |
|   const setting = event.target.getAttribute('data-setting');
 | |
|   const option = event.target.getAttribute('data-option');
 | |
|   const type = event.target.getAttribute('data-type');
 | |
| 
 | |
|   switch(type){
 | |
|     case 'weight':
 | |
|       settings[setting][option] = isNaN(event.target.value) ? event.target.value : parseInt(event.target.value, 10);
 | |
|       document.getElementById(`${setting}-${option}`).innerText = event.target.value;
 | |
|       break;
 | |
|     case 'data':
 | |
|       settings[setting] = isNaN(event.target.value) ? event.target.value : parseInt(event.target.value, 10);
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   localStorage.setItem('weighted-settings', JSON.stringify(settings));
 | |
| };
 | |
| 
 | |
| const updateGameSetting = (event) => {
 | |
|   const options = JSON.parse(localStorage.getItem('weighted-settings'));
 | |
|   const game = event.target.getAttribute('data-game');
 | |
|   const setting = event.target.getAttribute('data-setting');
 | |
|   const option = event.target.getAttribute('data-option');
 | |
|   const type = event.target.getAttribute('data-type');
 | |
|   document.getElementById(`${game}-${setting}-${option}`).innerText = event.target.value;
 | |
|   options[game][setting][option] = isNaN(event.target.value) ?
 | |
|       event.target.value : parseInt(event.target.value, 10);
 | |
|   localStorage.setItem('weighted-settings', JSON.stringify(options));
 | |
| };
 | |
| 
 | |
| const exportSettings = () => {
 | |
|   const settings = JSON.parse(localStorage.getItem('weighted-settings'));
 | |
|   if (!settings.name || settings.name.trim().length === 0 || settings.name.toLowerCase().trim() === 'player') {
 | |
|     const userMessage = document.getElementById('user-message');
 | |
|     userMessage.innerText = 'You forgot to set your player name at the top of the page!';
 | |
|     userMessage.classList.add('visible');
 | |
|     window.scrollTo(0, 0);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // Clean up the settings output
 | |
|   Object.keys(settings.game).forEach((game) => {
 | |
|     // Remove any disabled games
 | |
|     if (settings.game[game] === 0) {
 | |
|       delete settings.game[game];
 | |
|       delete settings[game];
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     // Remove any disabled options
 | |
|     Object.keys(settings[game]).forEach((setting) => {
 | |
|       Object.keys(settings[game][setting]).forEach((option) => {
 | |
|         if (settings[game][setting][option] === 0) {
 | |
|           delete settings[game][setting][option];
 | |
|         }
 | |
|       });
 | |
|     });
 | |
|   });
 | |
| 
 | |
|   const yamlText = jsyaml.safeDump(settings, { noCompatMode: true }).replaceAll(/'(\d+)':/g, (x, y) => `${y}:`);
 | |
|   download(`${document.getElementById('player-name').value}.yaml`, yamlText);
 | |
| };
 | |
| 
 | |
| /** Create an anchor and trigger a download of a text file. */
 | |
| const download = (filename, text) => {
 | |
|   const downloadLink = document.createElement('a');
 | |
|   downloadLink.setAttribute('href','data:text/yaml;charset=utf-8,'+ encodeURIComponent(text))
 | |
|   downloadLink.setAttribute('download', filename);
 | |
|   downloadLink.style.display = 'none';
 | |
|   document.body.appendChild(downloadLink);
 | |
|   downloadLink.click();
 | |
|   document.body.removeChild(downloadLink);
 | |
| };
 | |
| 
 | |
| const generateGame = (raceMode = false) => {
 | |
|   axios.post('/api/generate', {
 | |
|     weights: { player: localStorage.getItem('weighted-settings') },
 | |
|     presetData: { player: localStorage.getItem('weighted-settings') },
 | |
|     playerCount: 1,
 | |
|     race: raceMode ? '1' : '0',
 | |
|   }).then((response) => {
 | |
|     window.location.href = response.data.url;
 | |
|   }).catch((error) => {
 | |
|     const userMessage = document.getElementById('user-message');
 | |
|     userMessage.innerText = 'Something went wrong and your game could not be generated.';
 | |
|     if (error.response.data.text) {
 | |
|       userMessage.innerText += ' ' + error.response.data.text;
 | |
|     }
 | |
|     userMessage.classList.add('visible');
 | |
|     window.scrollTo(0, 0);
 | |
|     console.error(error);
 | |
|   });
 | |
| };
 |