diff --git a/assets/en/svg/text/scene/stage/tx_fesmatch-2cee60cbe41a1594b8d5ef867138f99d843cfce6efe0c490a41632b2e99ec685.svg b/assets/en/svg/text/scene/stage/tx_fesmatch-2cee60cbe41a1594b8d5ef867138f99d843cfce6efe0c490a41632b2e99ec685.svg new file mode 100644 index 0000000..68a41fe --- /dev/null +++ b/assets/en/svg/text/scene/stage/tx_fesmatch-2cee60cbe41a1594b8d5ef867138f99d843cfce6efe0c490a41632b2e99ec685.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/assets/en/svg/ui/ico_stage_fes-d2041f3d0fc360ad6c7c00dc4f5bfd1aa626a251d35af88c076b5498d8eb991d.svg b/assets/en/svg/ui/ico_stage_fes-d2041f3d0fc360ad6c7c00dc4f5bfd1aa626a251d35af88c076b5498d8eb991d.svg new file mode 100644 index 0000000..ced91a5 --- /dev/null +++ b/assets/en/svg/ui/ico_stage_fes-d2041f3d0fc360ad6c7c00dc4f5bfd1aa626a251d35af88c076b5498d8eb991d.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/en/ui/Splatnet_its_splatfest_time!.png b/assets/en/ui/Splatnet_its_splatfest_time!.png new file mode 100644 index 0000000..0b35a35 Binary files /dev/null and b/assets/en/ui/Splatnet_its_splatfest_time!.png differ diff --git a/stages/stages.js b/stages/stages.js index 80731a2..af3fbb6 100644 --- a/stages/stages.js +++ b/stages/stages.js @@ -105,7 +105,7 @@ window.loadHeader(async function(headerContainer) { if (nameEl) { const parsedName = miiBlob ? extractMiiName(miiBlob) : null; - nameEl.textContent = parsedName || (data.mii && data.mii.name) || data.nickname || data.user_id || data.username || "User"; + nameEl.textContent = parsedName || (data.mii && data.mii.name) || data.nickname || data.user_id || data.username || "Loading..."; } if (imgEl && miiBlob) { @@ -189,13 +189,39 @@ async function fetchRotations() { const res = await fetch(API_URL); if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`); const data = await res.json(); - const rotations = data?.pretendo?.rotations ?? {}; const now = new Date(); - let allData = Object.keys(rotations).map(ts => { + + const fest = data?.splatfestivalSplatfest; + let currentFest = null; + + if (fest && fest.stages && fest.stages.length > 0) { + const festStart = new Date(fest.time.start * 1000); + const festEnd = new Date(fest.time.end * 1000); + + if (now >= festStart && now <= festEnd) { + currentFest = { + isFest: true, + turf: stageNames(fest.stages), + startTime: festStart, + endTime: festEnd, + isExpired: false + }; + } + } + + if (currentFest) { + return [currentFest]; + } + + const rotations = data?.pretendo?.rotations ?? {}; + + let standardRotations = Object.keys(rotations).map(ts => { const start = new Date(Number(ts)); - const end = new Date(start.getTime() + 2 * 60 * 60 * 1000); const r = rotations[ts]; + const end = new Date(start.getTime() + (r.duration * 60 * 60 * 1000)); + return { + isFest: false, turf: stageNames(r.turfStages), ranked: stageNames(r.rankedStages), ranked_mode: r.rankedMode.replace(/([a-z])([A-Z])/g, "$1 $2"), @@ -204,8 +230,10 @@ async function fetchRotations() { isExpired: end < now }; }); - const active = allData.filter(r => !r.isExpired).sort((a, b) => a.startTime - b.startTime); - const past = allData.filter(r => r.isExpired).sort((a, b) => b.startTime - a.startTime); + + const active = standardRotations.filter(r => !r.isExpired).sort((a, b) => a.startTime - b.startTime); + const past = standardRotations.filter(r => r.isExpired).sort((a, b) => b.startTime - a.startTime); + return [...active, ...past]; } catch (error) { console.error(error); @@ -215,32 +243,25 @@ async function fetchRotations() { async function renderStages() { const container = document.getElementById("stages-container"); - try { allRotations = await fetchRotations(); if (!allRotations.length) { container.innerHTML = `

Something went wrong! Try reloading the page.

`; return; } - container.innerHTML = ""; - const trigger = document.createElement('div'); trigger.id = 'scroll-trigger'; trigger.style.height = '10px'; trigger.style.display = 'none'; container.after(trigger); - loadMore(true); - observer = new IntersectionObserver((entries) => { if (entries.isIntersecting && currentIndex > 0 && currentIndex < allRotations.length) { loadMore(false); } }, { rootMargin: '0px 0px 100px 0px' }); - observer.observe(trigger); - } catch (err) { console.error(err); } @@ -253,9 +274,7 @@ function loadMore(isInitial) { if (!isInitial && loadingOverlay) { loadingOverlay.style.display = 'flex'; - if (typeof window.animateLoadingCanvas === 'function') { - window.animateLoadingCanvas(); - } + if (typeof window.animateLoadingCanvas === 'function') window.animateLoadingCanvas(); } const waitTime = isInitial ? 0 : 800; @@ -267,8 +286,6 @@ function loadMore(isInitial) { nextBatch.forEach((rotation, index) => { const isFirstItem = isInitial && index === 0; - const isAboutToExpire = !rotation.isExpired && (rotation.endTime - now) < (15 * 60 * 1000); - const optionsDate = { day: "2-digit", month: "2-digit", year: "numeric" }; const optionsTime = { hour: "numeric", minute: "2-digit", hour12: true }; const timeZone = "Europe/Paris"; @@ -280,60 +297,79 @@ function loadMore(isInitial) { const formattedTime = `${startDay} at ${startTime} (CEST) ~ ${endDay} at ${endTime} (CEST)`; - if (isFirstItem) { - if (isAboutToExpire) { - html += `
NOTICE: This rotation is about to expire!
`; - } else if (rotation.isExpired) { - html += `
NOTICE: This rotation has expired!
`; + if (rotation.isFest) { + html += ` +
+ Its Splatfest Time! +
+
${formattedTime}
+
+
+ Splatfest +
Splatfest Battle
+
+
+ ${rotation.turf.map(name => ` +
+
+
${name}
+
+ `).join("")} +
+
+ `; + } else { + if (isFirstItem) { + const isAboutToExpire = !rotation.isExpired && (rotation.endTime - now) < (15 * 60 * 1000); + if (isAboutToExpire) { + html += `
NOTICE: This rotation is about to expire!
`; + } else if (rotation.isExpired) { + html += `
NOTICE: This rotation has expired!
`; + } } - } - html += ` -
${formattedTime}
-
-
- Regular Battle -
Regular Battle
+ html += ` +
${formattedTime}
+
+
+ Regular Battle +
Regular Battle
+
+
+ ${rotation.turf.map(name => ` +
+
+
${name}
+
+ `).join("")} +
-
- ${rotation.turf.map(name => ` -
-
-
${name}
-
- `).join("")} +
+
+ Ranked Battle +
Ranked Battle
+
+
+
Battle Mode
+
${rotation.ranked_mode}
+
+
+ ${rotation.ranked.map(name => ` +
+
+
${name}
+
+ `).join("")} +
-
-
-
- Ranked Battle -
Ranked Battle
-
-
-
Battle Mode
-
${rotation.ranked_mode}
-
-
- ${rotation.ranked.map(name => ` -
-
-
${name}
-
- `).join("")} -
-
- `; + `; + } }); container.insertAdjacentHTML('beforeend', html); - currentIndex += ITEMS_PER_PAGE; - + currentIndex += nextBatch.length; if (!isInitial && loadingOverlay) loadingOverlay.style.display = 'none'; if (trigger) trigger.style.display = 'block'; - - if (currentIndex >= allRotations.length) { - if (observer) observer.disconnect(); - if (trigger) trigger.remove(); - } + if (currentIndex >= allRotations.length && trigger) trigger.remove(); }, waitTime); } \ No newline at end of file diff --git a/stages/styles.css b/stages/styles.css index b0fec59..cd3ab51 100644 --- a/stages/styles.css +++ b/stages/styles.css @@ -322,4 +322,16 @@ body { .sprite-linkedin { width: 30px; height: 30px; background-position: -1385px -745px; background-size: initial; aspect-ratio: 1/1; } .sprite-stackoverflow { width: 30px; height: 30px; background-position: -1425px -745px; background-size: initial; aspect-ratio: 1/1; } .sprite-tumblr { width: 30px; height: 30px; background-position: -1465px -745px; background-size: initial; aspect-ratio: 1/1; } -.sprite-twitter { width: 30px; height: 30px; background-position: -1505px -745px; background-size: initial; aspect-ratio: 1/1; } \ No newline at end of file +.sprite-twitter { width: 30px; height: 30px; background-position: -1505px -745px; background-size: initial; aspect-ratio: 1/1; } + +.splatfest-banner-container { + text-align: center; + width: 100%; + margin-bottom: 30px; +} +.its-splatfest-time { + max-width: auto; + height: 120%; + display: block; + margin: 0 auto; +} \ No newline at end of file