1034 lines
33 KiB
JavaScript
1034 lines
33 KiB
JavaScript
import translate from "./translate-hints.js";
|
|
import update from "./fetch-updates.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;
|
|
|
|
// Global state internal
|
|
var server_address = "localhost:51111/";
|
|
var can_access_api_server = false;
|
|
var is_timeout = false;
|
|
var hide_completed_areas = false;
|
|
var cross_codes = {};
|
|
var total_checks = 0;
|
|
var total_entrances = 0;
|
|
var all_scenes = [];
|
|
|
|
window.onload = async () => {
|
|
await get_updated_server_address();
|
|
await parse_cross_codes();
|
|
// await initialize_elements();
|
|
await refresh_elements();
|
|
};
|
|
|
|
async function parse_cross_codes() {
|
|
fetch(`${document.URL}static/tracker/data/holy_cross_codes.json`)
|
|
.then((response) => response.json())
|
|
.then(
|
|
(data) => {
|
|
cross_codes = JSON.parse(JSON.stringify(data));
|
|
},
|
|
(error) => {
|
|
console.error(error);
|
|
}
|
|
);
|
|
}
|
|
|
|
async function get_updated_server_address() {
|
|
fetch(`${document.URL}get/address`)
|
|
.then(
|
|
(response) => response.json(),
|
|
(error) => {
|
|
console.error(error);
|
|
}
|
|
)
|
|
.then(
|
|
(data) => {
|
|
const parsed_data = JSON.parse(JSON.stringify(data));
|
|
server_address = parsed_data["listen_address"];
|
|
},
|
|
(error) => {
|
|
console.error(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 update.refresh_overview(server_address);
|
|
if (!overview) {
|
|
return;
|
|
}
|
|
// console.log(overview)
|
|
const checks = await update.refresh_checks(server_address);
|
|
if (!checks) {
|
|
return;
|
|
}
|
|
const entrances = await update.refresh_entrances(server_address);
|
|
if (!entrances) {
|
|
return;
|
|
}
|
|
const hints = await update.refresh_hints(server_address);
|
|
if (!hints) {
|
|
return;
|
|
}
|
|
|
|
|
|
// Initialize global state
|
|
current_checks = checks.collected;
|
|
current_entrances = entrances.found;
|
|
total_checks = checks.total;
|
|
total_entrances = entrances.total;
|
|
all_scenes = Array.from(Object.keys(checks.scenes));
|
|
await update_overview(overview, false);
|
|
|
|
// Initialize breakdown list
|
|
let breakdown_list = document
|
|
.getElementById("breakdown-list")
|
|
.cloneNode(true);
|
|
let summary_list = document.getElementById("summary-list").cloneNode(true);
|
|
|
|
// Initialize the breakdown and summary lists
|
|
breakdown_list = await initialize_breakdown_list(
|
|
breakdown_list,
|
|
checks,
|
|
entrances
|
|
);
|
|
summary_list = await initialize_summary_list(summary_list, checks, entrances);
|
|
|
|
// Replace breakdown list
|
|
document
|
|
.getElementById("breakdown-list")
|
|
.replaceWith(breakdown_list.cloneNode(true));
|
|
|
|
// Replace summary list
|
|
document
|
|
.getElementById("summary-list")
|
|
.replaceWith(summary_list.cloneNode(true));
|
|
|
|
// Update codes list
|
|
update_codes(overview.codes);
|
|
|
|
// Update hints list
|
|
update_hints(hints);
|
|
return;
|
|
}
|
|
|
|
async function refresh_elements() {
|
|
try {
|
|
const response = await update.fetch_api(server_address, "overview");
|
|
|
|
// Check if the "Hide completed areas" option is checked
|
|
hide_completed_areas = document.getElementById("hideDone").checked;
|
|
|
|
if (response.data) {
|
|
if (!can_access_api_server) {
|
|
console.info("I found the server!");
|
|
document.getElementById("status-block").classList.add("hidden");
|
|
can_access_api_server = true;
|
|
await initialize_elements();
|
|
}
|
|
is_timeout = false;
|
|
await update_if_changes(response.data);
|
|
setTimeout(refresh_elements, 500)
|
|
} else if (response.error) {
|
|
setTimeout(refresh_elements, 1100)
|
|
if (response.error.error) {
|
|
if (!is_timeout) {
|
|
is_timeout = true;
|
|
console.debug("Received timeout from API server.");
|
|
}
|
|
if (!can_access_api_server) {
|
|
console.info("I found the server!");
|
|
document.getElementById("status-block").classList.add("hidden");
|
|
can_access_api_server = true;
|
|
}
|
|
} else {
|
|
if (can_access_api_server) {
|
|
console.debug("Could not access the API server.");
|
|
document.getElementById("status-block").classList.remove("hidden");
|
|
}
|
|
can_access_api_server = false;
|
|
}
|
|
} else {
|
|
if (can_access_api_server) {
|
|
console.debug("Could not access the API server.");
|
|
document.getElementById("status-block").classList.remove("hidden");
|
|
}
|
|
can_access_api_server = false;
|
|
setTimeout(refresh_elements, 1100)
|
|
}
|
|
|
|
} catch (error) {
|
|
setTimeout(refresh_elements, 1100)
|
|
}
|
|
|
|
|
|
}
|
|
|
|
async function update_if_changes(overview) {
|
|
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
|
|
);
|
|
await 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) {
|
|
initialize_elements();
|
|
console.info(`Seed changed to: ${current_seed}`);
|
|
} else {
|
|
if (changed_checks) {
|
|
update.refresh_checks(server_address).then((data) => {
|
|
update_breakdown_list(data, { entrances: false, checks: true });
|
|
update_summary_list(data, { entrances: false, checks: true });
|
|
});
|
|
}
|
|
if (changed_entrances) {
|
|
update.refresh_entrances(server_address).then((data) => {
|
|
update_breakdown_list(data, { entrances: true, checks: false });
|
|
update_summary_list(data, { entrances: true, checks: false });
|
|
});
|
|
}
|
|
if (changed_hints) {
|
|
update.refresh_hints(server_address).then((data) => update_hints(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)`;
|
|
|
|
// Set global state
|
|
current_seed = overview.seed;
|
|
current_scene = overview.scene;
|
|
current_checks = overview.items;
|
|
current_entrances = overview.entrances;
|
|
current_hints = overview.hints;
|
|
|
|
if (changed_scene && all_scenes.some((scene) => scene == overview.scene)) {
|
|
await update_scene(overview.scene);
|
|
}
|
|
}
|
|
|
|
async function update_codes(codes) {
|
|
// Codes that are always active
|
|
const default_cross_codes = cross_codes.Default;
|
|
|
|
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"
|
|
).firstElementChild.alt = cross_codes["Global"][codename]
|
|
.replace(/U/g, "⬆️")
|
|
.replace(/R/g, "➡️")
|
|
.replace(/D/g, "⬇️")
|
|
.replace(/L/g, "⬅️");
|
|
cross_codes_block_list_item.querySelector(
|
|
".codes-list-item-code"
|
|
).firstElementChild.src = `/static/tracker/images/cross_codes/Global/${codename}.png`;
|
|
} else {
|
|
cross_codes_block_list_item.querySelector(
|
|
".codes-list-item-code"
|
|
).firstElementChild.alt = cross_codes[current_scene][codename]
|
|
.replace(/U/g, "⬆️")
|
|
.replace(/R/g, "➡️")
|
|
.replace(/D/g, "⬇️")
|
|
.replace(/L/g, "⬅️");
|
|
cross_codes_block_list_item.querySelector(
|
|
".codes-list-item-code"
|
|
).firstElementChild.src = `/static/tracker/images/cross_codes/${current_scene}/${codename}.png`;
|
|
}
|
|
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"
|
|
).firstElementChild.alt = default_cross_codes[code]
|
|
.replace(/U/g, "⬆️")
|
|
.replace(/R/g, "➡️")
|
|
.replace(/D/g, "⬇️")
|
|
.replace(/L/g, "⬅️");
|
|
cross_codes_block_list_item.querySelector(
|
|
".codes-list-item-code"
|
|
).firstElementChild.src = `/static/tracker/images/cross_codes/Default/${code}.png`;
|
|
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.entrances_total > 0) {
|
|
if (summary.checks_total > 0) {
|
|
if (summary.checks_remaining > 0 || summary.entrances_remaining > 0) {
|
|
if (summary.checks_remaining <= 0 || summary.entrances_remaining <= 0) {
|
|
if (summary.checks_remaining == 0) {
|
|
summary.element.classList.add(
|
|
"from-highlight-entrances-light",
|
|
"to-highlight-entrances-dark",
|
|
"text-highlight-entrances-text"
|
|
);
|
|
} else {
|
|
summary.element.classList.add(
|
|
"from-highlight-checks-light",
|
|
"to-highlight-checks-dark",
|
|
"text-highlight-checks-text"
|
|
);
|
|
}
|
|
} else {
|
|
if (summary.entrances_found <= 0) {
|
|
summary.element.classList.add(
|
|
"from-highlight-undiscovered-light",
|
|
"to-highlight-undiscovered-dark",
|
|
"text-highlight-undiscovered-text"
|
|
);
|
|
}
|
|
summary.element.classList.add(
|
|
"from-highlight-both-light",
|
|
"to-highlight-both-dark",
|
|
"text-highlight-both-text"
|
|
);
|
|
}
|
|
} else {
|
|
summary.element.classList.add(
|
|
"from-highlight-empty-light",
|
|
"to-highlight-empty-dark",
|
|
"text-highlight-empty-text"
|
|
);
|
|
}
|
|
} else {
|
|
if (summary.entrances_remaining > 0) {
|
|
if (summary.entrances_found <= 0) {
|
|
summary.element.classList.add(
|
|
"from-highlight-undiscovered-light",
|
|
"to-highlight-undiscovered-dark",
|
|
"text-highlight-undiscovered-text"
|
|
);
|
|
} else {
|
|
summary.element.classList.add(
|
|
"from-highlight-entrances-light",
|
|
"to-highlight-entrances-dark",
|
|
"text-highlight-entrances-text"
|
|
);
|
|
}
|
|
} else {
|
|
summary.element.classList.add(
|
|
"from-highlight-empty-light",
|
|
"to-highlight-empty-dark",
|
|
"text-highlight-empty-text"
|
|
);
|
|
}
|
|
}
|
|
} else {
|
|
if (summary.checks_total > 0 && summary.checks_remaining > 0) {
|
|
summary.element.classList.add(
|
|
"from-highlight-checks-light",
|
|
"to-highlight-checks-dark",
|
|
"text-highlight-checks-text"
|
|
);
|
|
} else {
|
|
summary.element.classList.add(
|
|
"from-highlight-empty-light",
|
|
"to-highlight-empty-dark",
|
|
"text-highlight-empty-text"
|
|
);
|
|
}
|
|
}
|
|
|
|
return summary.element;
|
|
}
|
|
|
|
async function initialize_breakdown_list(breakdown_list, checks, entrances) {
|
|
// Initialize breakdown list
|
|
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");
|
|
|
|
for (const scene of Object.keys(checks.scenes)) {
|
|
// Initialize breakdown element
|
|
breakdown_list_item = await initialize_breakdown(
|
|
breakdown_list_item,
|
|
scene,
|
|
checks.scenes[scene],
|
|
entrances.scenes[scene]
|
|
);
|
|
|
|
// Add breakdown element to breakdown list
|
|
breakdown_list.appendChild(breakdown_list_item.cloneNode(true));
|
|
}
|
|
|
|
// Return initialized breakdown list
|
|
return breakdown_list;
|
|
}
|
|
|
|
async function initialize_breakdown(
|
|
breakdown_element,
|
|
scene,
|
|
checks,
|
|
entrances
|
|
) {
|
|
// Initialize breakdown data
|
|
breakdown_element.dataset.scene = scene;
|
|
breakdown_element.querySelector(".breakdown-block-title").textContent = scene;
|
|
|
|
// Populate breakdown lists
|
|
const breakdown_checks_list =
|
|
breakdown_element.querySelector(".breakdown-checks");
|
|
const breakdown_entrances_list = breakdown_element.querySelector(
|
|
".breakdown-entrances"
|
|
);
|
|
const breakdown_mapped_list = breakdown_element.querySelector(
|
|
".breakdown-block-mapped-list"
|
|
);
|
|
const new_breakdown_checks_list = await initialize_checks_list(
|
|
breakdown_checks_list,
|
|
checks
|
|
);
|
|
const new_entrances_lists = await initialize_entrances_list(
|
|
breakdown_entrances_list,
|
|
breakdown_mapped_list,
|
|
entrances
|
|
);
|
|
|
|
// Replace checks, entrances, and mapped lists
|
|
breakdown_element
|
|
.querySelector(".breakdown-checks")
|
|
.replaceWith(new_breakdown_checks_list);
|
|
breakdown_element
|
|
.querySelector(".breakdown-entrances")
|
|
.replaceWith(new_entrances_lists.entrances_list);
|
|
breakdown_element
|
|
.querySelector(".breakdown-block-mapped-list")
|
|
.replaceWith(new_entrances_lists.mapped_list);
|
|
|
|
// Hide breakdowns that aren't for the current scene
|
|
if (current_scene == scene) {
|
|
breakdown_element.classList.add("order-first");
|
|
breakdown_element.classList.remove("hidden", "order-last");
|
|
breakdown_element.dataset.current = true;
|
|
} else {
|
|
breakdown_element.classList.add("hidden", "order-last");
|
|
breakdown_element.classList.remove("order-first");
|
|
breakdown_element.dataset.current = false;
|
|
}
|
|
|
|
// Return initialized breakdown
|
|
return breakdown_element;
|
|
}
|
|
|
|
async function initialize_checks_list(checks_list, checks) {
|
|
// Initialize new checks list for the breakdown
|
|
let new_breakdown_block_checks_list = checks_list
|
|
.querySelector(".breakdown-block-checks-list")
|
|
.cloneNode(true);
|
|
let breakdown_block_checks_list_item =
|
|
new_breakdown_block_checks_list.firstElementChild.cloneNode(true);
|
|
|
|
// Clear new checks list and append blank entry
|
|
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");
|
|
|
|
// Update the check totals
|
|
checks_list.querySelector(
|
|
".breakdown-block-checks-title"
|
|
).textContent = `Checks: ${checks.collected}/${checks.total} (${checks.remaining} left)`;
|
|
checks_list.querySelector(
|
|
".breakdown-block-checks-title"
|
|
).dataset.checksCollected = checks.collected;
|
|
checks_list.querySelector(
|
|
".breakdown-block-checks-title"
|
|
).dataset.checksRemaining = checks.remaining;
|
|
checks_list.querySelector(
|
|
".breakdown-block-checks-title"
|
|
).dataset.checksTotal = checks.total;
|
|
|
|
// Populate new checks list
|
|
Object.keys(checks.checks).forEach((check) => {
|
|
if (checks.checks[check].name == "") {
|
|
breakdown_block_checks_list_item.classList.remove("hidden");
|
|
} else {
|
|
breakdown_block_checks_list_item.classList.add("hidden");
|
|
}
|
|
breakdown_block_checks_list_item.textContent = `❌ ${check}`;
|
|
breakdown_block_checks_list_item.dataset.check = check;
|
|
new_breakdown_block_checks_list.appendChild(
|
|
breakdown_block_checks_list_item.cloneNode(true)
|
|
);
|
|
});
|
|
|
|
// Replace checks list
|
|
checks_list
|
|
.querySelector(".breakdown-block-checks-list")
|
|
.replaceWith(new_breakdown_block_checks_list);
|
|
|
|
return checks_list;
|
|
}
|
|
|
|
async function initialize_entrances_list(
|
|
entrances_list,
|
|
mapped_list,
|
|
entrances
|
|
) {
|
|
// Create new entrances and mapped lists and append empty entrance and mapped element
|
|
let new_breakdown_block_entrances_list = entrances_list
|
|
.querySelector(".breakdown-block-entrances-list")
|
|
.cloneNode(true);
|
|
let 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(
|
|
breakdown_block_entrances_list_item.cloneNode(true)
|
|
);
|
|
breakdown_block_entrances_list_item.classList.remove("hidden");
|
|
|
|
let new_breakdown_block_mapped_list = mapped_list.cloneNode(true);
|
|
let 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(
|
|
breakdown_block_mapped_list_item.cloneNode(true)
|
|
);
|
|
breakdown_block_mapped_list_item.classList.remove("hidden");
|
|
|
|
// Update the entrance totals
|
|
entrances_list.querySelector(
|
|
".breakdown-block-entrances-title"
|
|
).textContent = `Entrances: ${entrances.found}/${entrances.total} (${entrances.remaining} left)`;
|
|
entrances_list.querySelector(
|
|
".breakdown-block-entrances-title"
|
|
).dataset.entrancesFound = entrances.found;
|
|
entrances_list.querySelector(
|
|
".breakdown-block-entrances-title"
|
|
).dataset.entrancesRemaining = entrances.remaining;
|
|
entrances_list.querySelector(
|
|
".breakdown-block-entrances-title"
|
|
).dataset.entrancesTotal = entrances.total;
|
|
|
|
// Populate new entrances and mapped lists
|
|
Object.keys(entrances.doors).forEach((entrance) => {
|
|
breakdown_block_entrances_list_item.dataset.entrance = entrance;
|
|
breakdown_block_entrances_list_item.textContent = `❌ ${entrance}`;
|
|
breakdown_block_mapped_list_item.dataset.mapped = entrance;
|
|
if (entrances.doors[entrance].door == "") {
|
|
breakdown_block_entrances_list_item.classList.remove("hidden");
|
|
new_breakdown_block_entrances_list.appendChild(
|
|
breakdown_block_entrances_list_item.cloneNode(true)
|
|
);
|
|
breakdown_block_mapped_list_item.textContent = `✔️ ${entrance} -> `;
|
|
breakdown_block_mapped_list_item.dataset.scene = "";
|
|
breakdown_block_mapped_list_item.classList.add("hidden");
|
|
new_breakdown_block_mapped_list.appendChild(
|
|
breakdown_block_mapped_list_item.cloneNode(true)
|
|
);
|
|
} else {
|
|
breakdown_block_entrances_list_item.classList.add("hidden");
|
|
new_breakdown_block_entrances_list.appendChild(
|
|
breakdown_block_entrances_list_item.cloneNode(true)
|
|
);
|
|
breakdown_block_mapped_list_item.textContent = `✔️ ${entrance} -> ${entrances.doors[entrance].door}`;
|
|
breakdown_block_mapped_list_item.dataset.scene =
|
|
entrances.doors[entrance].scene;
|
|
breakdown_block_mapped_list_item.classList.remove("hidden");
|
|
new_breakdown_block_mapped_list.appendChild(
|
|
breakdown_block_mapped_list_item.cloneNode(true)
|
|
);
|
|
}
|
|
});
|
|
|
|
entrances_list
|
|
.querySelector(".breakdown-block-entrances-list")
|
|
.replaceWith(new_breakdown_block_entrances_list);
|
|
|
|
// Return entrance and mapped list elements
|
|
return {
|
|
entrances_list: entrances_list,
|
|
mapped_list: new_breakdown_block_mapped_list,
|
|
};
|
|
}
|
|
|
|
async function initialize_summary_list(summary_list, checks, entrances) {
|
|
// Initialize summary list
|
|
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");
|
|
|
|
for (const scene of Object.keys(checks.scenes)) {
|
|
// Initialize summary element
|
|
summary_list_item = await initialize_summary(
|
|
summary_list_item,
|
|
scene,
|
|
checks.scenes[scene],
|
|
entrances.scenes[scene]
|
|
);
|
|
|
|
// Add summary element to summary list
|
|
summary_list.firstElementChild.appendChild(
|
|
summary_list_item.cloneNode(true)
|
|
);
|
|
}
|
|
|
|
// Return initialized summary list
|
|
return summary_list;
|
|
}
|
|
|
|
async function initialize_summary(summary_element, scene, checks, entrances) {
|
|
// Initialize summary data
|
|
summary_element.dataset.scene = scene;
|
|
summary_element.querySelector(".summary-title").textContent = scene;
|
|
|
|
const summary_checks = summary_element.querySelector(".summary-checks");
|
|
summary_checks.dataset.checksCollected = checks.collected;
|
|
summary_checks.dataset.checksRemaining = checks.remaining;
|
|
summary_checks.dataset.checksTotal = checks.total;
|
|
summary_checks.textContent = `Checks: ${checks.collected}/${checks.total} (${checks.remaining})`;
|
|
|
|
const summary_entrances = summary_element.querySelector(".summary-entrances");
|
|
summary_entrances.dataset.entrancesFound = entrances.found;
|
|
summary_entrances.dataset.entrancesRemaining = entrances.remaining;
|
|
summary_entrances.dataset.entrancesTotal = entrances.total;
|
|
summary_entrances.textContent = `Entrances: ${entrances.found}/${entrances.total} (${entrances.remaining})`;
|
|
|
|
// Apply summary color coding
|
|
summary_element.firstElementChild.replaceWith(
|
|
await apply_summary_colors({
|
|
element: summary_element.firstElementChild,
|
|
checks_collected: checks.collected,
|
|
checks_remaining: checks.remaining,
|
|
checks_total: checks.total,
|
|
entrances_found: entrances.found,
|
|
entrances_remaining: entrances.remaining,
|
|
entrances_total: entrances.total,
|
|
})
|
|
);
|
|
|
|
// Hide summaries for scenes with no entrances and the current scene and completed areas if "Hide completed areas" is checked
|
|
if ((entrances.total <= 0 && checks.total <= 0) || current_scene == scene) {
|
|
summary_element.dataset.current = current_scene == scene;
|
|
summary_element.classList.add("hidden");
|
|
} else {
|
|
if (hide_completed_areas) {
|
|
if (checks.remaining > 0 && entrances.remaining > 0) {
|
|
summary_element.classList.remove("hidden");
|
|
} else {
|
|
summary_element.classList.add("hidden");
|
|
}
|
|
} else {
|
|
summary_element.dataset.current = false;
|
|
summary_element.classList.remove("hidden");
|
|
}
|
|
}
|
|
|
|
// Return initialized summary
|
|
return summary_element;
|
|
}
|
|
|
|
async function update_summary(scene, checks, entrances) {
|
|
// Grab summary checks and entrances
|
|
const summary_checks = document.querySelector(
|
|
`.summary[data-scene="${scene}"] .summary-checks`
|
|
);
|
|
const summary_entrances = document.querySelector(
|
|
`.summary[data-scene="${scene}"] .summary-entrances`
|
|
);
|
|
|
|
// Make variables for whether checks or entrances updated
|
|
const checks_changed =
|
|
summary_checks.dataset.checksCollected != checks.collected;
|
|
const entrances_changed =
|
|
summary_entrances.dataset.entrancesFound != entrances.found;
|
|
|
|
// Check for changes, and if so, update
|
|
if (checks_changed) {
|
|
summary_checks.dataset.checksCollected = checks.collected;
|
|
summary_checks.dataset.checksRemaining = checks.remaining;
|
|
summary_checks.dataset.checksTotal = checks.total;
|
|
summary_checks.textContent = `Checks: ${checks.collected}/${checks.total} (${checks.remaining})`;
|
|
}
|
|
if (entrances_changed) {
|
|
summary_entrances.dataset.entrancesFound = entrances.found;
|
|
summary_entrances.dataset.entrancesRemaining = entrances.remaining;
|
|
summary_entrances.dataset.entrancesTotal = entrances.total;
|
|
summary_entrances.textContent = `Entrances: ${entrances.found}/${entrances.total} (${entrances.remaining})`;
|
|
}
|
|
|
|
// Apply color coding
|
|
if (checks_changed || entrances_changed) {
|
|
document
|
|
.querySelector(`.summary[data-scene="${scene}"]`)
|
|
.firstElementChild.replaceWith(
|
|
await apply_summary_colors({
|
|
element: document.querySelector(`.summary[data-scene="${scene}"]`)
|
|
.firstElementChild,
|
|
checks_collected: checks.collected,
|
|
checks_remaining: checks.remaining,
|
|
checks_total: checks.total,
|
|
entrances_found: entrances.found,
|
|
entrances_remaining: entrances.remaining,
|
|
entrances_total: entrances.total,
|
|
})
|
|
);
|
|
}
|
|
}
|
|
|
|
async function update_summary_list(data, changed) {
|
|
// Check whether entrances or checks changed
|
|
if (changed.checks && current_checks > 0) {
|
|
Object.keys(data.scenes).forEach((scene) =>
|
|
update_summary(scene, data.scenes[scene], {
|
|
found: document.querySelector(
|
|
`.summary[data-scene="${scene}"] .summary-entrances`
|
|
).dataset.entrancesFound,
|
|
remaining: document.querySelector(
|
|
`.summary[data-scene="${scene}"] .summary-entrances`
|
|
).dataset.entrancesRemaining,
|
|
total: document.querySelector(
|
|
`.summary[data-scene="${scene}"] .summary-entrances`
|
|
).dataset.entrancesTotal,
|
|
})
|
|
);
|
|
} else if (changed.entrances && current_entrances > 0) {
|
|
Object.keys(data.scenes).forEach((scene) =>
|
|
update_summary(
|
|
scene,
|
|
{
|
|
collected: document.querySelector(
|
|
`.summary[data-scene="${scene}"] .summary-checks`
|
|
).dataset.checksCollected,
|
|
remaining: document.querySelector(
|
|
`.summary[data-scene="${scene}"] .summary-checks`
|
|
).dataset.checksRemaining,
|
|
total: document.querySelector(
|
|
`.summary[data-scene="${scene}"] .summary-checks`
|
|
).dataset.checksTotal,
|
|
},
|
|
data.scenes[scene]
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
async function update_breakdown_checks(scene, checks) {
|
|
// Update the check totals
|
|
document.querySelector(
|
|
`.breakdown[data-scene="${scene}"] .breakdown-block-checks-title`
|
|
).textContent = `Checks: ${checks.collected}/${checks.total} (${checks.remaining} left)`;
|
|
document.querySelector(
|
|
`.breakdown[data-scene="${scene}"] .breakdown-block-checks-title`
|
|
).dataset.checksCollected = checks.collected;
|
|
document.querySelector(
|
|
`.breakdown[data-scene="${scene}"] .breakdown-block-checks-title`
|
|
).dataset.checksRemaining = checks.remaining;
|
|
document.querySelector(
|
|
`.breakdown[data-scene="${scene}"] .breakdown-block-checks-title`
|
|
).dataset.checksTotal = checks.total;
|
|
|
|
// Hide collected checks
|
|
for (const check of Object.keys(checks.checks)) {
|
|
const check_item = document.querySelector(
|
|
`.breakdown[data-scene="${scene}"] [data-check="${check}"]`
|
|
);
|
|
if (checks.checks[check].name == "") {
|
|
check_item.classList.remove("hidden");
|
|
} else {
|
|
check_item.classList.add("hidden");
|
|
}
|
|
}
|
|
}
|
|
|
|
async function update_breakdown_entrances(scene, entrances) {
|
|
// Update the entrance totals
|
|
document.querySelector(
|
|
`.breakdown[data-scene="${scene}"] .breakdown-block-entrances-title`
|
|
).textContent = `Entrances: ${entrances.found}/${entrances.total} (${entrances.remaining} left)`;
|
|
document.querySelector(
|
|
`.breakdown[data-scene="${scene}"] .breakdown-block-entrances-title`
|
|
).dataset.entrancesFound = entrances.found;
|
|
document.querySelector(
|
|
`.breakdown[data-scene="${scene}"] .breakdown-block-entrances-title`
|
|
).dataset.entrancesRemaining = entrances.remaining;
|
|
document.querySelector(
|
|
`.breakdown[data-scene="${scene}"] .breakdown-block-entrances-title`
|
|
).dataset.entrancesTotal = entrances.total;
|
|
|
|
// Map found entrances
|
|
for (const entrance of Object.keys(entrances.doors)) {
|
|
const entrance_item = document.querySelector(
|
|
`.breakdown[data-scene="${scene}"] [data-entrance="${entrance}"]`
|
|
);
|
|
const mapped_item = document.querySelector(
|
|
`.breakdown[data-scene="${scene}"] [data-mapped="${entrance}"]`
|
|
);
|
|
if (entrances.doors[entrance].door == "") {
|
|
entrance_item.classList.remove("hidden");
|
|
mapped_item.classList.add("hidden");
|
|
} else {
|
|
entrance_item.classList.add("hidden");
|
|
mapped_item.classList.remove("hidden");
|
|
mapped_item.dataset.scene = entrances.doors[entrance].scene;
|
|
mapped_item.textContent = `✔️ ${entrance} -> ${entrances.doors[entrance].door}`;
|
|
}
|
|
}
|
|
}
|
|
|
|
async function update_breakdown(scene, checks, entrances) {
|
|
// Grab breakdown checks and entrances
|
|
const breakdown_checks = document.querySelector(
|
|
`.breakdown[data-scene="${scene}"] .breakdown-block-checks-title`
|
|
);
|
|
const breakdown_entrances = document.querySelector(
|
|
`.breakdown[data-scene="${scene}"] .breakdown-block-entrances-title`
|
|
);
|
|
|
|
// Check for changes, and if so, update
|
|
if (breakdown_checks.dataset.checksCollected != checks.collected) {
|
|
update_breakdown_checks(scene, checks);
|
|
}
|
|
if (breakdown_entrances.dataset.entrancesFound != entrances.found) {
|
|
update_breakdown_entrances(scene, entrances);
|
|
}
|
|
}
|
|
|
|
async function update_breakdown_list(data, changed) {
|
|
// Check whether entrances or checks changed
|
|
if (changed.checks) {
|
|
Object.keys(data.scenes).forEach((scene) =>
|
|
update_breakdown(scene, data.scenes[scene], {
|
|
found: document.querySelector(
|
|
`.breakdown[data-scene="${scene}"] .breakdown-block-entrances-title`
|
|
).dataset.entrancesFound,
|
|
})
|
|
);
|
|
} else if (changed.entrances) {
|
|
Object.keys(data.scenes).forEach((scene) =>
|
|
update_breakdown(
|
|
scene,
|
|
{
|
|
collected: document.querySelector(
|
|
`.breakdown[data-scene="${scene}"] .breakdown-block-checks-title`
|
|
).dataset.checksCollected,
|
|
},
|
|
data.scenes[scene]
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
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");
|
|
for (const hint_index of Object.keys(hints)) {
|
|
hints[hint_index] = await translate.parse_hints(hints[hint_index]);
|
|
hints_list_item.firstElementChild.innerHTML = hints[hint_index];
|
|
hints_list.appendChild(hints_list_item.cloneNode(true));
|
|
}
|
|
document.getElementById("hints-list").replaceWith(hints_list);
|
|
}
|
|
|
|
async function update_scene(scene) {
|
|
// Grab current scene and updated scene breakdown/summary elements
|
|
const current_breakdown_old = document.querySelector(
|
|
`.breakdown[data-current="true"]`
|
|
);
|
|
const current_breakdown = document.querySelector(
|
|
`.breakdown[data-scene="${scene}"]`
|
|
);
|
|
const current_summary_old = document.querySelector(
|
|
`.summary[data-current="true"]`
|
|
);
|
|
const current_summary = document.querySelector(
|
|
`.summary[data-scene="${scene}"]`
|
|
);
|
|
|
|
// Update the current breakdown
|
|
current_breakdown_old.dataset.current = false;
|
|
current_breakdown_old.classList.add("hidden", "order-last");
|
|
current_breakdown_old.classList.remove("order-first");
|
|
current_breakdown.dataset.current = true;
|
|
current_breakdown.classList.add("order-first");
|
|
current_breakdown.classList.remove("hidden", "order-last");
|
|
const old_checks_remaining = parseInt(
|
|
current_summary_old.querySelector(".summary-checks").dataset.checksRemaining
|
|
);
|
|
const old_entrances_remaining = parseInt(
|
|
current_summary_old.querySelector(".summary-entrances").dataset
|
|
.entrancesRemaining
|
|
);
|
|
const old_checks_total = parseInt(
|
|
current_summary_old.querySelector(".summary-checks").dataset.checksTotal
|
|
);
|
|
const old_entrances_total = parseInt(
|
|
current_summary_old.querySelector(".summary-entrances").dataset
|
|
.entrancesTotal
|
|
);
|
|
|
|
// Update the current summary
|
|
current_summary_old.dataset.current = false;
|
|
if (hide_completed_areas) {
|
|
if (old_checks_remaining > 0 && old_entrances_remaining > 0) {
|
|
current_summary_old.classList.remove("hidden");
|
|
} else {
|
|
current_summary_old.classList.add("hidden");
|
|
if (old_entrances_total <= 0 && old_checks_total <= 0) {
|
|
current_summary_old.classList.add("hidden");
|
|
} else {
|
|
current_summary_old.classList.remove("hidden");
|
|
}
|
|
}
|
|
} else {
|
|
if (old_entrances_total <= 0 && old_checks_total <= 0) {
|
|
current_summary_old.classList.add("hidden");
|
|
} else {
|
|
current_summary_old.classList.remove("hidden");
|
|
}
|
|
}
|
|
current_summary.dataset.current = true;
|
|
current_summary.classList.add("hidden");
|
|
}
|