2026-01-30 23:53:01 +01:00
const API _URL = "https://api.splatcord.ink/prod/s1rotations" ;
function stageNames ( stages , lang = "en-US" ) {
return stages . map ( s => s . translatedNames [ lang ] ) ;
}
function stageImagePath ( stageName ) {
const firstWord = stageName
. split ( " " ) [ 0 ]
. toLowerCase ( )
. replace ( /['.]/g , "" ) ;
return ` /assets/stages/ ${ firstWord } .png ` ;
}
async function fetchRotations ( ) {
try {
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 ( ) ;
const timestamps = Object . keys ( rotations ) . sort ( ( a , b ) => Number ( a ) - Number ( b ) ) ;
const result = [ ] ;
for ( const ts of timestamps ) {
const start = new Date ( Number ( ts ) ) ;
const end = new Date ( start . getTime ( ) + 2 * 60 * 60 * 1000 ) ;
if ( end < now ) continue ;
const r = rotations [ ts ] ;
result . push ( {
turf : stageNames ( r . turfStages ) ,
ranked : stageNames ( r . rankedStages ) ,
ranked _mode : r . rankedMode . replace ( /([a-z])([A-Z])/g , "$1 $2" ) ,
startTime : start ,
endTime : end ,
} ) ;
}
return result ;
} catch ( error ) {
console . error ( "Failed to fetch rotations:" , error ) ;
return [ ] ;
}
}
async function renderStages ( ) {
const loadingOverlay = document . getElementById ( "loading-overlay" ) ;
const container = document . getElementById ( "stages-container" ) ;
let rotations = [ ] ;
try {
rotations = await fetchRotations ( ) ;
} catch ( err ) {
console . error ( "Error in renderStages:" , err ) ;
} finally {
loadingOverlay . style . display = "none" ;
}
2026-02-03 04:19:38 +01:00
2026-01-30 23:53:01 +01:00
if ( ! rotations . length ) {
2026-02-03 04:19:38 +01:00
container . innerHTML = ` <h2 class="error-message">Something went wrong! Try reloading the page.</h2> ` ;
2026-01-30 23:53:01 +01:00
return ;
}
let html = "" ;
for ( const rotation of rotations ) {
const optionsDate = { day : "2-digit" , month : "2-digit" } ;
const optionsTime = { hour : "numeric" , minute : "2-digit" , hour12 : true } ;
const timeZone = "Europe/Paris" ;
2026-02-03 04:19:38 +01:00
const formattedTime = ` ${ rotation . startTime . toLocaleDateString ( "en-GB" , { ... optionsDate , timeZone } )} at ${ rotation . startTime . toLocaleTimeString ( "en-GB" , { ... optionsTime , timeZone } )} (CEST) ~ ${ rotation . endTime . toLocaleDateString ( "en-GB" , { ... optionsDate , timeZone } )} at ${ rotation . endTime . toLocaleTimeString ( "en-GB" , { ... optionsTime , timeZone } )} (CEST) ` ;
2026-01-30 23:53:01 +01:00
html += `
< div class = "rotation-time" > $ { formattedTime } < / d i v >
< div class = "stages-section" >
2026-02-03 04:19:38 +01:00
< div class = "mode-header" >
< img class = "mode-title" src = "/assets/en/svg/ui/ico_stage_regular-54557ab86d0cba16cf002e6d299f87dccb41655de8a171d32928bfebda3f3692.svg" alt = "Regular Battle" >
2026-02-03 04:38:47 +01:00
< div class = "mode-text" > < img src = "/assets/en/svg/text/scene/stage/tx_regularmatch-2cee60cbe41a1594b8d5ef867138f99d843cfce6efe0c490a41632b2e99ec685.svg" alt = "Regular Battle" > < / d i v >
2026-02-03 04:19:38 +01:00
< / d i v >
2026-01-30 23:53:01 +01:00
< div class = "stages" >
2026-02-03 04:19:38 +01:00
$ { rotation . turf . map ( name => `
< div class = "stage-item" >
2026-01-30 23:53:01 +01:00
< img src = "${stageImagePath(name)}" alt = "${name}" >
< div class = "stage-title" > $ { name } < / d i v >
< / d i v >
2026-02-03 04:19:38 +01:00
` ).join("")}
2026-01-30 23:53:01 +01:00
< / d i v >
< / d i v >
< div class = "stages-section" >
2026-02-03 04:19:38 +01:00
< div class = "mode-header" >
< img class = "mode-title" src = "/assets/en/svg/ui/ico_stage_gachi-d2041f3d0fc360ad6c7c00dc4f5bfd1aa626a251d35af88c076b5498d8eb991d.svg" alt = "Ranked Battle" >
2026-02-03 04:38:47 +01:00
< div class = "mode-text" > < img src = "/assets/en/svg/text/scene/stage/tx_gachimatch-08a066c73d4dcf466c435be611b996ffd7930d19d9a6a865b712cd5dd802534f.svg" alt = "Ranked Battle" > < / d i v >
2026-02-03 04:19:38 +01:00
< / d i v >
2026-01-30 23:53:01 +01:00
< div class = "ranked-mode-labels" >
2026-02-03 04:38:47 +01:00
< div class = "battle-mode-text" > < img src = "/assets/en/svg/text/scene/stage/tx_rule-76cf0777fb715a9478f8b579512541f3f14ed834566e0b6e153834a57d726021.svg" alt = "Battle Mode" > < / d i v >
2026-01-30 23:53:01 +01:00
< div class = "ranked-mode-text" > $ { rotation . ranked _mode } < / d i v >
< / d i v >
2026-02-03 04:19:38 +01:00
2026-01-30 23:53:01 +01:00
< div class = "stages" >
2026-02-03 04:19:38 +01:00
$ { rotation . ranked . map ( name => `
< div class = "stage-item" >
2026-01-30 23:53:01 +01:00
< img src = "${stageImagePath(name)}" alt = "${name}" >
< div class = "stage-title" > $ { name } < / d i v >
< / d i v >
2026-02-03 04:19:38 +01:00
` ).join("")}
2026-01-30 23:53:01 +01:00
< / d i v >
< / d i v >
` ;
}
container . innerHTML = html ;
}
renderStages ( ) ;