| (() => { |
| "use strict"; |
|
|
| const data = window.EGOSUITE_DATA; |
| if (!data) { |
| document.body.innerHTML = "<p>Dashboard data failed to load.</p>"; |
| return; |
| } |
|
|
| const state = { |
| environmentId: data.environments[0].id, |
| skuId: "egofull", |
| distributionMode: "normalized", |
| overlayEnabled: true |
| }; |
|
|
| const elements = { |
| donutSlices: document.querySelector("#donut-slices"), |
| donutValue: document.querySelector("#donut-value"), |
| donutLabel: document.querySelector("#donut-label"), |
| environmentList: document.querySelector("#environment-list"), |
| distributionBadge: document.querySelector("#distribution-badge"), |
| mediaStage: document.querySelector("#media-stage"), |
| mediaVideo: document.querySelector("#media-video"), |
| mediaPoster: document.querySelector("#media-poster"), |
| mediaState: document.querySelector("#media-state"), |
| mediaTitle: document.querySelector("#media-title"), |
| mediaEnvironment: document.querySelector("#media-environment"), |
| mediaSku: document.querySelector("#media-sku"), |
| mediaCapture: document.querySelector("#media-capture"), |
| skuDescription: document.querySelector("#sku-description"), |
| capabilityList: document.querySelector("#capability-list"), |
| sceneList: document.querySelector("#scene-list"), |
| poseOverlay: document.querySelector("#pose-overlay"), |
| overlayToggle: document.querySelector("#overlay-toggle"), |
| taskTable: document.querySelector("#task-table"), |
| skuShowcase: document.querySelector("#sku-showcase") |
| }; |
|
|
| const number = new Intl.NumberFormat("en-US", { maximumFractionDigits: 2 }); |
|
|
| function getEnvironment() { |
| return data.environments.find((item) => item.id === state.environmentId); |
| } |
|
|
| function getSku() { |
| return data.skus[state.skuId]; |
| } |
|
|
| function environmentHours(environment) { |
| return state.distributionMode === "normalized" |
| ? environment.normalizedHours |
| : environment.rawHours; |
| } |
|
|
| function environmentRatio(environment) { |
| return state.distributionMode === "normalized" |
| ? environment.normalizedRatio |
| : environment.suppliedRatio; |
| } |
|
|
| function renderDonut() { |
| elements.donutSlices.replaceChildren(); |
| let offset = 0; |
|
|
| data.environments.forEach((environment) => { |
| const geometryRatio = environment.normalizedRatio; |
| const slice = document.createElementNS("http://www.w3.org/2000/svg", "circle"); |
| slice.setAttribute("class", "donut-slice"); |
| slice.setAttribute("cx", "120"); |
| slice.setAttribute("cy", "120"); |
| slice.setAttribute("r", "82"); |
| slice.setAttribute("pathLength", "100"); |
| slice.setAttribute("stroke", environment.color); |
| slice.setAttribute("stroke-dasharray", `${geometryRatio} ${100 - geometryRatio}`); |
| slice.setAttribute("stroke-dashoffset", `${-offset}`); |
| slice.setAttribute("tabindex", "0"); |
| slice.setAttribute("role", "button"); |
| slice.setAttribute( |
| "aria-label", |
| `${environment.en}, ${number.format(environmentHours(environment))} hours, ${number.format(environmentRatio(environment))} percent` |
| ); |
| slice.dataset.environment = environment.id; |
| slice.classList.toggle("is-selected", environment.id === state.environmentId); |
|
|
| const choose = () => selectEnvironment(environment.id); |
| slice.addEventListener("mouseenter", choose); |
| slice.addEventListener("focus", choose); |
| slice.addEventListener("click", choose); |
| slice.addEventListener("keydown", (event) => { |
| if (event.key === "Enter" || event.key === " ") { |
| event.preventDefault(); |
| choose(); |
| } |
| }); |
|
|
| elements.donutSlices.append(slice); |
| offset += geometryRatio; |
| }); |
| } |
|
|
| function renderEnvironmentList() { |
| elements.environmentList.replaceChildren(); |
|
|
| data.environments.forEach((environment) => { |
| const row = document.createElement("button"); |
| row.type = "button"; |
| row.className = "environment-row"; |
| row.dataset.environment = environment.id; |
| row.style.setProperty("--row-color", environment.color); |
| row.classList.toggle("is-selected", environment.id === state.environmentId); |
| row.setAttribute("role", "listitem"); |
|
|
| const name = document.createElement("span"); |
| name.className = "environment-name"; |
| name.innerHTML = ` |
| <span class="environment-swatch" aria-hidden="true"></span> |
| <span><strong>${environment.en}</strong><span>${environment.zh}</span></span> |
| `; |
|
|
| const value = document.createElement("span"); |
| value.className = "environment-value"; |
| value.innerHTML = ` |
| <strong>${number.format(environmentHours(environment))}h</strong> |
| <span>${number.format(environment.clips)} clips</span> |
| `; |
|
|
| const ratio = document.createElement("span"); |
| ratio.className = "environment-ratio"; |
| ratio.textContent = `${number.format(environmentRatio(environment))}%`; |
|
|
| row.append(name, value, ratio); |
| row.addEventListener("mouseenter", () => selectEnvironment(environment.id)); |
| row.addEventListener("focus", () => selectEnvironment(environment.id)); |
| row.addEventListener("click", () => selectEnvironment(environment.id)); |
| elements.environmentList.append(row); |
| }); |
| } |
|
|
| function updateDistributionStatus() { |
| const normalized = state.distributionMode === "normalized"; |
| elements.distributionBadge.textContent = normalized |
| ? "NORMALIZED TO 10K" |
| : "RAW INPUT 路 119.7%"; |
| elements.distributionBadge.classList.toggle("status-ok", normalized); |
| elements.distributionBadge.classList.toggle("status-warning", !normalized); |
|
|
| document.querySelectorAll("[data-distribution]").forEach((button) => { |
| const active = button.dataset.distribution === state.distributionMode; |
| button.classList.toggle("is-active", active); |
| button.setAttribute("aria-pressed", String(active)); |
| }); |
| } |
|
|
| function selectEnvironment(environmentId) { |
| if (state.environmentId === environmentId) { |
| updateSelectionState(); |
| return; |
| } |
| state.environmentId = environmentId; |
| updateSelectionState(); |
| updateMedia(); |
| } |
|
|
| function updateSelectionState() { |
| const environment = getEnvironment(); |
| elements.donutValue.textContent = `${number.format(environmentHours(environment))}h`; |
| elements.donutLabel.textContent = environment.en; |
|
|
| document.querySelectorAll("[data-environment]").forEach((item) => { |
| item.classList.toggle("is-selected", item.dataset.environment === state.environmentId); |
| }); |
| } |
|
|
| function updateMedia() { |
| const environment = getEnvironment(); |
| const sku = getSku(); |
|
|
| elements.mediaStage.classList.remove("is-changing"); |
| void elements.mediaStage.offsetWidth; |
| elements.mediaStage.classList.add("is-changing"); |
| elements.mediaStage.dataset.sku = sku.id; |
|
|
| elements.mediaTitle.textContent = `${environment.en} 路 ${sku.name}`; |
| elements.mediaEnvironment.textContent = environment.en.toUpperCase(); |
| elements.mediaSku.textContent = `${sku.name} 路 ${number.format(sku.hours)}h`; |
| elements.mediaCapture.textContent = sku.capture; |
| elements.skuDescription.textContent = sku.description; |
| elements.sceneList.textContent = environment.scenes.join(" 路 "); |
|
|
| elements.capabilityList.replaceChildren(); |
| sku.capabilities.forEach((capability) => { |
| const item = document.createElement("span"); |
| item.className = "capability"; |
| item.textContent = capability; |
| elements.capabilityList.append(item); |
| }); |
|
|
| if (environment.videoUrl) { |
| elements.mediaPoster.hidden = true; |
| elements.mediaVideo.hidden = false; |
| if (elements.mediaVideo.getAttribute("src") !== environment.videoUrl) { |
| elements.mediaVideo.src = environment.videoUrl; |
| } |
| elements.mediaVideo.play().catch(() => {}); |
| elements.mediaState.textContent = "AUDITED RAW VIDEO"; |
| elements.mediaState.classList.remove("status-warning"); |
| elements.mediaState.classList.add("status-ok"); |
| } else { |
| elements.mediaVideo.pause(); |
| elements.mediaVideo.hidden = true; |
| elements.mediaPoster.hidden = false; |
| elements.mediaPoster.src = environment.poster; |
| elements.mediaPoster.alt = `${environment.en} environment poster preview`; |
| elements.mediaState.textContent = "POSTER TEST MEDIA"; |
| elements.mediaState.classList.add("status-warning"); |
| elements.mediaState.classList.remove("status-ok"); |
| } |
|
|
| elements.skuShowcase.src = sku.showcase; |
| elements.skuShowcase.alt = `${sku.name} multimodal showcase`; |
| } |
|
|
| function setSku(skuId) { |
| state.skuId = skuId; |
| document.querySelectorAll("[data-sku]").forEach((button) => { |
| if (!button.matches("button")) return; |
| const active = button.dataset.sku === skuId; |
| button.classList.toggle("is-active", active); |
| button.setAttribute("aria-pressed", String(active)); |
| }); |
| updateMedia(); |
| } |
|
|
| function setDistributionMode(mode) { |
| state.distributionMode = mode; |
| updateDistributionStatus(); |
| renderDonut(); |
| renderEnvironmentList(); |
| updateSelectionState(); |
| } |
|
|
| function renderTasks() { |
| elements.taskTable.replaceChildren(); |
| data.tasks.forEach((task) => { |
| const row = document.createElement("div"); |
| row.className = "task-row"; |
| row.classList.toggle("is-pending", task.status === "pending_audit"); |
| row.setAttribute("role", "row"); |
|
|
| const statusLabel = task.status === "pending_audit" ? "Pending" : "Name supplied"; |
| row.innerHTML = ` |
| <span class="task-rank">${String(task.rank).padStart(2, "0")}</span> |
| <span class="task-name"><strong>${task.en}</strong><span>${task.zh}</span></span> |
| <span class="task-status">${statusLabel}</span> |
| `; |
| elements.taskTable.append(row); |
| }); |
| } |
|
|
| document.querySelectorAll("[data-sku]").forEach((button) => { |
| if (button.matches("button")) { |
| button.addEventListener("click", () => setSku(button.dataset.sku)); |
| } |
| }); |
|
|
| document.querySelectorAll("[data-distribution]").forEach((button) => { |
| button.addEventListener("click", () => setDistributionMode(button.dataset.distribution)); |
| }); |
|
|
| elements.overlayToggle.addEventListener("change", () => { |
| state.overlayEnabled = elements.overlayToggle.checked; |
| elements.poseOverlay.classList.toggle("is-hidden", !state.overlayEnabled); |
| }); |
|
|
| renderDonut(); |
| renderEnvironmentList(); |
| renderTasks(); |
| updateDistributionStatus(); |
| updateSelectionState(); |
| updateMedia(); |
| })(); |
|
|