tunic-tracker-redux/tunictracker/tracker/static/tracker/assets/main.js

1002 lines
33 KiB
JavaScript

import translate from "./translate-hints.js";
// Global state for overview
var current_scene = "";
var current_seed = Number.MAX_VALUE;
var current_checks = 0;
var current_entrances = 0;
var current_codes = Number.MAX_VALUE;
var current_hints = 0;
var total_checks = 0;
var total_entrances = 0;
// Global state internal
var server_address = "localhost:51111";
var cross_codes = {};
var can_access_api_server = true;
window.onload = async () => {
await get_updated_server_address();
fetch(`${document.URL}static/tracker/data/holy_cross_codes.json`)
.then((response) => response.json())
.then(
(data) => {
cross_codes = JSON.parse(JSON.stringify(data));
initialize_elements();
refresh_elements();
},
(error) => {
console.log(error);
}
);
};
// A function to call when the page loads to ensure that we have the correct data when we connect to the server.
async function initialize_elements() {
// Grab all updates from the backend.
let overview = await refresh_overview();
if (!overview.overview) {
return;
}
const checks = await refresh_checks();
const entrances = await refresh_entrances();
const hints = await refresh_hints();
overview = overview.overview;
// Initialize overview data.
current_checks = checks.collected;
current_entrances = entrances.found;
total_checks = checks.total;
total_entrances = entrances.total;
update_overview(overview, true);
// Initialize breakdown list
let breakdown_list = document
.getElementById("breakdown-list")
.cloneNode(true);
let breakdown_list_item = breakdown_list.firstElementChild.cloneNode(true);
breakdown_list.innerHTML = "";
breakdown_list.appendChild(breakdown_list_item.cloneNode(true));
breakdown_list_item.classList.remove("hidden");
// Initialize summary list
let summary_list = document.getElementById("summary-list").cloneNode(true);
let summary_list_item =
summary_list.firstElementChild.firstElementChild.cloneNode(true);
summary_list.firstElementChild.innerHTML = "";
summary_list.firstElementChild.appendChild(summary_list_item.cloneNode(true));
summary_list_item.classList.remove("hidden");
// Initialize codes list
let codes_list = document.getElementById("codes-list").cloneNode(true);
let codes_list_item = codes_list.firstElementChild.cloneNode(true);
codes_list.innerHTML = "";
codes_list.appendChild(codes_list_item.cloneNode(true));
codes_list_item.classList.remove("hidden");
// Initialize hints list
let hints_list = document.getElementById("hints-list").cloneNode(true);
let hints_list_item = hints_list.firstElementChild.cloneNode(true);
hints_list.innerHTML = "";
hints_list.appendChild(hints_list_item.cloneNode(true));
hints_list_item.classList.remove("hidden");
// Populate the breakdown list
Object.keys(checks.scenes).forEach((scene) => {
// One-time update the title for each scene.
if (current_scene == scene) {
breakdown_list_item.dataset.current = "true";
breakdown_list_item.classList.remove("hidden", "order-last");
breakdown_list_item.classList.add("order-first");
} else {
breakdown_list_item.dataset.current = "false";
breakdown_list_item.classList.add("hidden", "order-last");
breakdown_list_item.classList.remove("order-first");
}
breakdown_list_item.dataset.breakdownScene = scene;
breakdown_list_item.querySelector(".breakdown-block-title").textContent =
scene;
// Populate checks data
breakdown_list_item.querySelector(
".breakdown-block-checks-title"
).textContent = `Checks: ${checks.scenes[scene].collected}/${checks.scenes[scene].total}/(${checks.scenes[scene].remaining} left)`;
breakdown_list_item.querySelector(
".breakdown-block-checks-title"
).dataset.checksCollected = checks.scenes[scene].collected;
breakdown_list_item.querySelector(
".breakdown-block-checks-title"
).dataset.checksRemaining = checks.scenes[scene].remaining;
breakdown_list_item.querySelector(
".breakdown-block-checks-title"
).dataset.checksTotal = checks.scenes[scene].total;
// Populate entrances data
breakdown_list_item.querySelector(
".breakdown-block-entrances-title"
).textContent = `Entrances: ${entrances.scenes[scene].found}/${entrances.scenes[scene].total}/(${entrances.scenes[scene].remaining} left)`;
breakdown_list_item.querySelector(
".breakdown-block-entrances-title"
).dataset.entrancesFound = entrances.scenes[scene].found;
breakdown_list_item.querySelector(
".breakdown-block-entrances-title"
).dataset.entrancesRemaining = entrances.scenes[scene].remaining;
breakdown_list_item.querySelector(
".breakdown-block-entrances-title"
).dataset.entrancesTotal = entrances.scenes[scene].total;
// Initialize checks list
let new_breakdown_block_checks_list = breakdown_list_item
.querySelector(".breakdown-block-checks-list")
.cloneNode(true);
let new_breakdown_block_checks_list_item =
new_breakdown_block_checks_list.firstElementChild.cloneNode(true);
new_breakdown_block_checks_list.innerHTML = "";
new_breakdown_block_checks_list.appendChild(
new_breakdown_block_checks_list_item.cloneNode(true)
);
new_breakdown_block_checks_list_item.classList.remove("hidden");
// Initialize entrances list
let new_breakdown_block_entrances_list = breakdown_list_item
.querySelector(".breakdown-block-entrances-list")
.cloneNode(true);
let new_breakdown_block_entrances_list_item =
new_breakdown_block_entrances_list.firstElementChild.cloneNode(true);
new_breakdown_block_entrances_list.innerHTML = "";
new_breakdown_block_entrances_list.appendChild(
new_breakdown_block_entrances_list_item.cloneNode(true)
);
new_breakdown_block_entrances_list_item.classList.remove("hidden");
// Initialize mapped list
let new_breakdown_block_mapped_list = breakdown_list_item
.querySelector(".breakdown-block-mapped-list")
.cloneNode(true);
let new_breakdown_block_mapped_list_item =
new_breakdown_block_mapped_list.firstElementChild.cloneNode(true);
new_breakdown_block_mapped_list.innerHTML = "";
new_breakdown_block_mapped_list.appendChild(
new_breakdown_block_mapped_list_item.cloneNode(true)
);
new_breakdown_block_mapped_list_item.classList.remove("hidden");
// Create checks list
Object.keys(checks.scenes[scene].checks).forEach((check) => {
new_breakdown_block_checks_list_item.textContent = `${check}`;
if (!checks.scenes[scene].checks[check].name) {
new_breakdown_block_checks_list.appendChild(
new_breakdown_block_checks_list_item.cloneNode(true)
);
}
});
// Create entrances list and mapped list
Object.keys(entrances.scenes[scene].doors).forEach((entrance) => {
if (!entrances.scenes[scene].doors[entrance].door) {
new_breakdown_block_entrances_list_item.textContent = `${entrance}`;
new_breakdown_block_entrances_list.appendChild(
new_breakdown_block_entrances_list_item.cloneNode(true)
);
} else {
new_breakdown_block_mapped_list_item.dataset.scene =
entrances.scenes[scene].doors[entrance].scene;
new_breakdown_block_mapped_list_item.textContent = `✔️ ${entrance} -> ${entrances.scenes[scene].doors[entrance].door}`;
new_breakdown_block_mapped_list.appendChild(
new_breakdown_block_mapped_list_item.cloneNode(true)
);
}
});
// Replace lists in breakdown
breakdown_list_item
.querySelector(".breakdown-block-checks-list")
.replaceWith(new_breakdown_block_checks_list.cloneNode(true));
breakdown_list_item
.querySelector(".breakdown-block-entrances-list")
.replaceWith(new_breakdown_block_entrances_list.cloneNode(true));
breakdown_list_item
.querySelector(".breakdown-block-mapped-list")
.replaceWith(new_breakdown_block_mapped_list.cloneNode(true));
// Add breakdown to list
breakdown_list.appendChild(breakdown_list_item.cloneNode(true));
});
// Populate the summary list
for (const scene of Object.keys(checks.scenes)) {
// One-time update data for scene
summary_list_item.dataset.scene = scene;
summary_list_item.querySelector(".summary-title").textContent = scene;
// Update checks and entrances
summary_list_item.dataset.checksCollected = checks.scenes[scene].collected;
summary_list_item.dataset.checksRemaining = checks.scenes[scene].remaining;
summary_list_item.dataset.checksTotal = checks.scenes[scene].total;
summary_list_item.querySelector(
".summary-checks"
).textContent = `Checks: ${checks.scenes[scene].collected}/${checks.scenes[scene].total} (${checks.scenes[scene].total})`;
summary_list_item.dataset.entrancesFound = entrances.scenes[scene].found;
summary_list_item.dataset.entrancesRemaining =
entrances.scenes[scene].remaining;
summary_list_item.dataset.entrancesTotal = entrances.scenes[scene].total;
summary_list_item.querySelector(
".summary-entrances"
).textContent = `Entrances: ${entrances.scenes[scene].found}/${entrances.scenes[scene].total} (${entrances.scenes[scene].total})`;
// Hide summaries for scenes with no entrances
if (entrances.scenes[scene].total <= 0) {
summary_list_item.classList.add("hidden");
} else {
summary_list_item.classList.remove("hidden");
}
// Apply color coding and add summary to list
summary_list_item.firstElementChild.replaceWith(
await apply_summary_colors({
element: summary_list_item.firstElementChild.cloneNode(true),
checks_collected: checks.scenes[scene].collected,
checks_total: checks.scenes[scene].total,
entrances_found: entrances.scenes[scene].found,
entrances_total: entrances.scenes[scene].total,
})
);
summary_list.firstElementChild.appendChild(
summary_list_item.cloneNode(true)
);
}
// Populate the codes list
Object.keys(overview.codes)
.sort((i, j) => {
return overview.codes[i].Distance - overview.codes[j].Distance;
})
.forEach((codename, index) => {
// One-time update data for code
codes_list_item.dataset.codename = codename;
codes_list_item.dataset.order = index;
codes_list_item.querySelector(".codes-list-item-title").textContent =
codename;
// Update code
if (overview.codes[codename].Global) {
codes_list_item.querySelector(".codes-list-item-code").textContent =
cross_codes["Global"][codename]
.replace(/U/g, "⬆️")
.replace(/R/g, "➡️")
.replace(/D/g, "⬇️")
.replace(/L/g, "⬅️");
} else {
codes_list_item.querySelector(".codes-list-item-code").textContent =
cross_codes[overview.scene][codename]
.replace(/U/g, "⬆️")
.replace(/R/g, "➡️")
.replace(/D/g, "⬇️")
.replace(/L/g, "⬅️");
}
// Add code to list
codes_list.appendChild(codes_list_item.cloneNode(true));
});
Object.keys(cross_codes.Default).forEach((codename) => {
// One-time update data for default code
codes_list_item.dataset.codename = codename;
codes_list_item.dataset.order = "last";
codes_list_item.querySelector(".codes-list-item-title").textContent =
codename;
// Update code
codes_list_item.querySelector(".codes-list-item-code").textContent =
cross_codes.Default[codename]
.replace(/U/g, "⬆️")
.replace(/R/g, "➡️")
.replace(/D/g, "⬇️")
.replace(/L/g, "⬅️");
// Add code to list
codes_list.appendChild(codes_list_item.cloneNode(true));
});
// Populate the hints list
Object.keys(hints).forEach((hint) => {
// Update hint
hints_list_item.firstElementChild.textContent = hints[hint];
// Add hint to list
hints_list.appendChild(hints_list_item.cloneNode(true));
});
// Replace breakdown list
document
.getElementById("breakdown-list")
.replaceWith(breakdown_list.cloneNode(true));
// Replace summary list
document
.getElementById("summary-list")
.replaceWith(summary_list.cloneNode(true));
// Replace codes list
document.getElementById("codes-list").replaceWith(codes_list.cloneNode(true));
// Replace hints list
document.getElementById("hints-list").replaceWith(hints_list.cloneNode(true));
// update_if_changes(overview);
// update_checks(checks);
// update_entrances(entrances);
// update_hints(hints);
return;
}
async function refresh_elements() {
const response = await refresh_overview();
if (response.overview) {
if (!can_access_api_server) {
console.log("I found the server!");
can_access_api_server = true;
await initialize_elements();
}
update_if_changes(response.overview);
} else {
if (can_access_api_server) {
console.log("Could not access the API server.");
}
can_access_api_server = false;
}
setTimeout(refresh_elements, 500);
}
async function update_if_changes(overview) {
document.getElementById("status-block").classList.add("hidden");
const changed_seed = overview.seed != current_seed;
const changed_scene = overview.scene != current_scene;
const changed_checks = overview.items != current_checks;
const changed_entrances = overview.entrances != current_entrances;
const changed_hints = overview.hints != current_hints;
const any_change =
changed_seed ||
changed_scene ||
changed_checks ||
changed_entrances ||
changed_hints;
if (any_change) {
await perform_updates(
changed_seed,
changed_checks,
changed_entrances,
changed_hints
);
update_overview(overview, changed_scene);
}
await update_codes(overview.codes);
}
async function perform_updates(
changed_seed,
changed_checks,
changed_entrances,
changed_hints
) {
if (changed_seed) {
// TODO: this at some point *needs* to initialize all the data when the seed changes, instead of relying on the initial HTML.
update_checks(await refresh_checks());
update_entrances(await refresh_entrances());
update_hints(await refresh_hints());
console.log(`Seed changed to: ${current_seed}`);
} else {
if (changed_checks) {
refresh_checks().then((data) => update_checks(data));
}
if (changed_entrances) {
refresh_entrances().then((data) => update_entrances(data));
}
if (changed_hints) {
refresh_hints().then((data) => update_hints(data));
}
}
}
async function get_updated_server_address() {
fetch(`${document.URL}get/address`)
.then(
(response) => response.json(),
(error) => {
console.log("Are you sure the front end is up?");
}
)
.then(
(data) => {
const parsed_data = JSON.parse(JSON.stringify(data));
server_address = parsed_data["listen_address"];
// if (parsed_data["backend_filepath_updated"]) {
// get_updated_filepath();
// }
},
(error) => {
console.log(error);
}
);
}
async function refresh_overview() {
try {
const response = await fetch(`${server_address}overview`);
if (response.ok) {
const data = await response.json();
if (!("error" in data)) {
return { overview: data, error: null };
}
}
return { overview: null, error: null };
} catch (e) {
return { overview: null, error: e };
}
}
async function refresh_hints() {
const response = await fetch(`${server_address}hints`);
const data = await response.json();
return data;
}
async function refresh_checks() {
const response = await fetch(`${server_address}items`);
const data = await response.json();
return data;
}
async function refresh_entrances() {
const response = await fetch(`${server_address}doors`);
const data = await response.json();
return data;
}
async function update_overview(overview, changed_scene) {
let overview_checks_title = document
.getElementById("overview-totals")
.querySelector(".overview-checks");
let overview_entrances_title = document
.getElementById("overview-totals")
.querySelector(".overview-entrances");
// Set content to updated data.
overview_checks_title.textContent = `${overview.items}/${total_checks} (${
total_checks - overview.items
} left)`;
overview_entrances_title.textContent = `${
overview.entrances * 2
}/${total_entrances} (${total_entrances - overview.entrances * 2} left)`;
current_seed = overview.seed;
current_scene = overview.scene;
current_checks = overview.items;
current_entrances = overview.entrances;
current_hints = overview.hints;
if (changed_scene) {
await update_scene(overview.scene);
}
}
async function update_codes(codes) {
// Codes that are always active
const default_cross_codes = cross_codes.Default;
// One time codes independent of scene
const global_cross_codes = cross_codes.Global;
let new_cross_codes_block_list = document
.getElementById("codes-list")
.cloneNode(true);
let cross_codes_block_list_item = document
.getElementById("codes-list")
.firstElementChild.cloneNode(true);
new_cross_codes_block_list.innerHTML = "";
new_cross_codes_block_list.appendChild(
cross_codes_block_list_item.cloneNode(true)
);
cross_codes_block_list_item.classList.remove("hidden");
const codes_length = Array.from(Object.keys(codes)).length;
if (current_codes != Array.from(Object.keys(codes)).length) {
Object.keys(codes)
.sort((i, j) => {
return codes[i].Distance - codes[j].Distance;
})
.forEach((codename, index) => {
cross_codes_block_list_item.querySelector(
".codes-list-item-title"
).textContent = codename;
if (codes[codename].Global) {
cross_codes_block_list_item.querySelector(
".codes-list-item-code"
).textContent = cross_codes["Global"][codename]
.replace(/U/g, "⬆️")
.replace(/R/g, "➡️")
.replace(/D/g, "⬇️")
.replace(/L/g, "⬅️");
} else {
cross_codes_block_list_item.querySelector(
".codes-list-item-code"
).textContent = cross_codes[current_scene][codename]
.replace(/U/g, "⬆️")
.replace(/R/g, "➡️")
.replace(/D/g, "⬇️")
.replace(/L/g, "⬅️");
}
cross_codes_block_list_item.dataset.codename = codename;
cross_codes_block_list_item.dataset.order = index;
new_cross_codes_block_list.appendChild(
cross_codes_block_list_item.cloneNode(true)
);
});
Object.keys(default_cross_codes).forEach((code) => {
cross_codes_block_list_item.querySelector(
".codes-list-item-title"
).textContent = code;
cross_codes_block_list_item.querySelector(
".codes-list-item-code"
).textContent = default_cross_codes[code]
.replace(/U/g, "⬆️")
.replace(/R/g, "➡️")
.replace(/D/g, "⬇️")
.replace(/L/g, "⬅️");
new_cross_codes_block_list.appendChild(
cross_codes_block_list_item.cloneNode(true)
);
});
document
.getElementById("codes-list")
.replaceWith(new_cross_codes_block_list);
// Change the number of current codes if it's different
current_codes = codes_length;
} else {
Object.keys(codes)
.sort((i, j) => {
return codes[i].Distance - codes[j].Distance;
})
.forEach((code, index) => {
const classes = Array.from(
document
.getElementById("codes-list")
.querySelector(`[data-codename="${code}"]`).classList
).filter((classname) => classname.startsWith("order-"));
if (classes.length > 0) {
document
.getElementById("codes-list")
.querySelector(`[data-codename="${code}"]`)
.classList.remove(classes);
}
if (codes[code].Global) {
document
.getElementById("codes-list")
.querySelector(`[data-codename="${code}"]`)
.classList.add(`order-last`);
} else {
document
.getElementById("codes-list")
.querySelector(`[data-codename="${code}"]`)
.classList.add(`order-${index + 1}`);
}
if (codes[code].InRange) {
document
.getElementById("codes-list")
.querySelector(`[data-codename="${code}"]`)
.classList.add(`bg-[#ffe28558]`);
} else {
document
.getElementById("codes-list")
.querySelector(`[data-codename="${code}"]`)
.classList.remove(`bg-[#ffe28558]`);
}
document
.getElementById("codes-list")
.querySelector(`[data-codename="${code}"]`).dataset.order = index + 1;
});
}
}
async function apply_summary_colors(summary) {
// Apply color coding to summary block
summary.element.classList.remove(
"from-highlight-both-light",
"from-highlight-checks-light",
"from-highlight-entrances-light",
"from-highlight-empty-light",
"from-highlight-undiscovered-light",
"to-highlight-both-dark",
"to-highlight-checks-dark",
"to-highlight-entrances-dark",
"to-highlight-empty-dark",
"to-highlight-undiscovered-dark",
"text-highlight-both-text",
"text-highlight-checks-text",
"text-highlight-entrances-text",
"text-highlight-empty-text",
"text-highlight-undiscovered-text"
);
if (summary.checks_total > 0 && summary.entrances_total > 0) {
if (
summary.checks_collected == summary.checks_total &&
summary.entrances_found == summary.entrances_total
) {
summary.element.classList.add(
"from-highlight-empty-light",
"to-highlight-empty-dark",
"text-highlight-empty-text"
);
} else if (
summary.checks_collected <= 0 &&
summary.entrances_found <= 0 &&
summary.entrances_total > 0
) {
summary.element.classList.add(
"from-highlight-undiscovered-light",
"to-highlight-undiscovered-dark",
"text-highlight-undiscovered-text"
);
} else if (summary.checks_collected >= summary.checks_total) {
summary.element.classList.add(
"from-highlight-checks-light",
"to-highlight-checks-dark",
"text-highlight-checks-text"
);
} else if (summary.entrances_found >= summary.entrances_total) {
summary.element.classList.add(
"from-highlight-entrances-light",
"to-highlight-entrances-dark",
"text-highlight-entrances-text"
);
} else {
summary.element.classList.add(
"from-highlight-both-light",
"to-highlight-both-dark",
"text-highlight-both-text"
);
}
} else {
summary.element.classList.add(
"from-highlight-undiscovered-light",
"to-highlight-undiscovered-dark",
"text-highlight-undiscovered-text"
);
}
return summary.element;
}
async function update_summary(updates) {
if ("checks" in updates) {
const summary_checks = document
.getElementById("summary-list")
.querySelector(`[data-scene="${updates.scene}"]`)
.querySelector(".summary-checks");
summary_checks.textContent = `Checks: ${updates.checks.collected}/${summary_checks.dataset.checksTotal} (${updates.checks.remaining})`;
summary_checks.dataset.checksUndiscovered = updates.checks.collected;
apply_summary_colors({
element: document
.getElementById("summary-list")
.querySelector(`[data-scene="${updates.scene}"]`).firstElementChild,
checks_collected: updates.checks.collected,
checks_total: summary_checks.dataset.checksTotal,
entrances_found: document
.getElementById("summary-list")
.querySelector(`[data-scene="${updates.scene}"]`)
.querySelector(".summary-entrances").dataset.entrancesUndiscovered,
entrances_total: document
.getElementById("summary-list")
.querySelector(`[data-scene="${updates.scene}"]`)
.querySelector(".summary-entrances").dataset.entrancesTotal,
});
} else if ("entrances" in updates) {
const summary_entrances = document
.getElementById("summary-list")
.querySelector(`[data-scene="${updates.scene}"]`)
.querySelector(".summary-entrances");
summary_entrances.textContent = `Entrances: ${updates.entrances.found}/${summary_entrances.dataset.entrancesTotal} (${updates.entrances.remaining})`;
summary_entrances.dataset.entrancesUndiscovered = updates.entrances.found;
apply_summary_colors({
element: document
.getElementById("summary-list")
.querySelector(`[data-scene="${updates.scene}"]`).firstElementChild,
checks_collected: document
.getElementById("summary-list")
.querySelector(`[data-scene="${updates.scene}"]`)
.querySelector(".summary-checks").dataset.checksUndiscovered,
checks_total: document
.getElementById("summary-list")
.querySelector(`[data-scene="${updates.scene}"]`)
.querySelector(".summary-checks").dataset.checksTotal,
entrances_found: updates.entrances.found,
entrances_total: summary_entrances.dataset.entrancesTotal,
});
} else {
console.log("What the heck is this");
}
}
async function update_checks(checks) {
total_checks = checks.total;
let new_breakdown_block_checks_list = document
.getElementById("breakdown-list")
.firstElementChild.querySelector(".breakdown-block-checks-list")
.cloneNode(true);
let breakdown_block_checks_list_item = document
.getElementById("breakdown-list")
.firstElementChild.querySelector(".breakdown-block-checks-list")
.firstElementChild.cloneNode(true);
// Create new lists with updated data.
let breakdown_list = Array.from(
document.getElementById("breakdown-list").children
);
breakdown_list.forEach((scene) => {
if (scene.querySelector(".breakdown-block-title").textContent) {
// Create variables for element pointers.
let scene_title = scene.querySelector(
".breakdown-block-title"
).textContent;
if (scene_title) {
const scene_checks = parseInt(
scene.querySelector(".breakdown-block-checks-title").dataset.checks
);
if (scene_checks != checks.scenes[scene_title].collected) {
scene.querySelector(".breakdown-block-checks-title").dataset.checks =
scene_checks;
update_summary({
scene: scene_title,
checks: {
collected: checks.scenes[scene_title].collected,
remaining: checks.scenes[scene_title].remaining,
},
});
scene.querySelector(
".breakdown-block-checks-title"
).textContent = `Checks: ${checks.scenes[scene_title].collected}/${checks.scenes[scene_title].total} (${checks.scenes[scene_title].remaining})`;
new_breakdown_block_checks_list.innerHTML = "";
new_breakdown_block_checks_list.appendChild(
breakdown_block_checks_list_item.cloneNode(true)
);
breakdown_block_checks_list_item.classList.remove("hidden");
Object.keys(checks.scenes[scene_title].checks).forEach((check) => {
if (checks.scenes[scene_title].checks[check].name == "") {
breakdown_block_checks_list_item.textContent = `${check}`;
new_breakdown_block_checks_list.appendChild(
breakdown_block_checks_list_item.cloneNode(true)
);
}
});
document
.getElementById("breakdown-list")
.querySelector(`[data-breakdown-scene="${scene_title}"]`)
.querySelector(".breakdown-block-checks-list").innerHTML = "";
document
.getElementById("breakdown-list")
.querySelector(`[data-breakdown-scene="${scene_title}"]`)
.querySelector(".breakdown-block-checks-list")
.replaceWith(new_breakdown_block_checks_list.cloneNode(true));
}
}
}
});
// current_checks = checks.collected;
}
async function update_entrances(entrances) {
total_entrances = entrances.total;
let new_breakdown_block_entrances_list = document
.getElementById("breakdown-list")
.firstElementChild.querySelector(".breakdown-block-entrances-list")
.cloneNode(true);
let breakdown_block_entrances_list_item = document
.getElementById("breakdown-list")
.firstElementChild.querySelector(".breakdown-block-entrances-list")
.firstElementChild.cloneNode(true);
let new_breakdown_block_mapped_list = document
.getElementById("breakdown-list")
.firstElementChild.querySelector(".breakdown-block-mapped-list")
.cloneNode(true);
let breakdown_block_mapped_list_item = document
.getElementById("breakdown-list")
.firstElementChild.querySelector(".breakdown-block-mapped-list")
.firstElementChild.cloneNode(true);
// Create new lists with updated data.
let breakdown_list = Array.from(
document.getElementById("breakdown-list").children
);
breakdown_list.forEach((scene) => {
if (scene.querySelector(".breakdown-block-title").textContent) {
// Create variables for element pointers.
let scene_title = scene.querySelector(
".breakdown-block-title"
).textContent;
if (scene_title) {
const scene_entrances = parseInt(
scene.querySelector(".breakdown-block-entrances-title").dataset
.entrances
);
if (scene_entrances != entrances.scenes[scene_title].found) {
scene.querySelector(
".breakdown-block-checks-title"
).dataset.entrances = scene_entrances;
update_summary({
scene: scene_title,
entrances: {
found: entrances.scenes[scene_title].found,
remaining: entrances.scenes[scene_title].remaining,
},
});
scene.querySelector(
".breakdown-block-entrances-title"
).textContent = `Entrances: ${entrances.scenes[scene_title].found}/${entrances.scenes[scene_title].total} (${entrances.scenes[scene_title].remaining})`;
new_breakdown_block_entrances_list.innerHTML = "";
new_breakdown_block_entrances_list.appendChild(
breakdown_block_entrances_list_item.cloneNode(true)
);
breakdown_block_entrances_list_item.classList.remove("hidden");
new_breakdown_block_mapped_list.innerHTML = "";
breakdown_block_mapped_list_item.classList.remove("hidden");
Object.keys(entrances.scenes[scene_title].doors).forEach(
(entrance) => {
if (entrances.scenes[scene_title].doors[entrance].door == "") {
breakdown_block_entrances_list_item.textContent = `${entrance}`;
new_breakdown_block_entrances_list.appendChild(
breakdown_block_entrances_list_item.cloneNode(true)
);
} else {
breakdown_block_mapped_list_item.textContent = `✔️ ${entrance} -> ${entrances.scenes[scene_title].doors[entrance].door}`;
breakdown_block_mapped_list_item.id = `${entrance}-mapped`;
breakdown_block_mapped_list_item.dataset.scene =
entrances.scenes[scene_title].doors[entrance].scene;
new_breakdown_block_mapped_list.appendChild(
breakdown_block_mapped_list_item.cloneNode(true)
);
}
}
);
document
.getElementById("breakdown-list")
.querySelector(`[data-breakdown-scene="${scene_title}"]`)
.querySelector(".breakdown-block-entrances-list").innerHTML = "";
document
.getElementById("breakdown-list")
.querySelector(`[data-breakdown-scene="${scene_title}"]`)
.querySelector(".breakdown-block-entrances-list")
.replaceWith(new_breakdown_block_entrances_list.cloneNode(true));
document
.getElementById("breakdown-list")
.querySelector(`[data-breakdown-scene="${scene_title}"]`)
.querySelector(".breakdown-block-mapped-list").innerHTML = "";
document
.getElementById("breakdown-list")
.querySelector(`[data-breakdown-scene="${scene_title}"]`)
.querySelector(".breakdown-block-mapped-list")
.replaceWith(new_breakdown_block_mapped_list.cloneNode(true));
}
}
}
});
}
async function update_hints(hints) {
let hints_list = document.getElementById("hints-list").cloneNode(true);
let hints_list_item = hints_list.firstElementChild.cloneNode(true);
hints_list.innerHTML = "";
hints_list.appendChild(hints_list_item.cloneNode(true));
hints_list_item.classList.remove("hidden");
Object.keys(hints).forEach((hint_index) => {
let hint = hints[hint_index].split(
/(\[[\w\s]+?\]|\"[\w \d\>\<#.\-\']+\"|\<[\w\d#]+\>)/gm
);
hint = hint.map((segment) => {
segment = segment.trim();
if (segment) {
if (
!(
segment.startsWith("[") ||
segment.startsWith("<") ||
segment.startsWith('"')
)
) {
segment = translate(segment.trim());
} else if (segment.startsWith("[")) {
segment = segment.trim();
} else {
segment = ` ${segment.trim()} `;
}
return segment;
}
});
hints[hint_index] = hint.join("");
});
Object.keys(hints).forEach((hint_index) => {
let hint = hints[hint_index];
let matches = Array.from(
hint.matchAll(/\<([\w\d#]+)\>(.*)(\<[\w\d#]+\>)/gm)
);
if (matches.length >= 1) {
hint = hint.replace(
/(\<[\w\d#]+\>.*\<[\w\d#]+\>)/gm,
`<span style="color: ${matches[0][1]};">${matches[0][2]}</span>`
);
}
hint = hint.replace(/ "|" /gm, " ");
hints_list_item.firstElementChild.innerHTML = hint;
hints_list.appendChild(hints_list_item.cloneNode(true));
});
document.getElementById("hints-list").innerHTML = "";
document.getElementById("hints-list").replaceWith(hints_list);
}
async function update_scene(scene) {
Array.from(document.getElementById("breakdown-list").children).forEach(
(breakdown) => {
const breakdown_title = breakdown.dataset.breakdownScene;
if (breakdown_title == scene) {
document
.getElementById("breakdown-list")
.querySelector(`[data-breakdown-scene="${scene}"]`)
.classList.remove("hidden");
document
.getElementById("breakdown-list")
.querySelector(`[data-breakdown-scene="${scene}"]`).dataset.current =
"true";
document
.getElementById("breakdown-list")
.querySelector(`[data-breakdown-scene="${scene}"]`)
.classList.remove("order-last");
document
.getElementById("breakdown-list")
.querySelector(`[data-breakdown-scene="${scene}"]`)
.classList.add("order-first");
} else {
document
.getElementById("breakdown-list")
.querySelector(
`[data-breakdown-scene="${breakdown_title}"]`
).dataset.current = "false";
document
.getElementById("breakdown-list")
.querySelector(`[data-breakdown-scene="${breakdown_title}"]`)
.classList.add("hidden");
document
.getElementById("breakdown-list")
.querySelector(`[data-breakdown-scene="${breakdown_title}"]`)
.classList.add("order-last");
document
.getElementById("breakdown-list")
.querySelector(`[data-breakdown-scene="${breakdown_title}"]`)
.classList.remove("order-first");
}
}
);
Array.from(
document.getElementById("summary-list").firstElementChild.children
).forEach((summary) => {
const summary_scene = summary.dataset.scene;
if (summary_scene == scene) {
document
.getElementById("summary-list")
.querySelector(`[data-scene="${scene}"]`)
.classList.add("hidden");
} else if (!(summary_scene == "")) {
document
.getElementById("summary-list")
.querySelector(`[data-scene="${summary_scene}"]`)
.classList.remove("hidden");
}
});
}