\n \n \n \n \n
\n Enjoying Chronoodle? Share your thoughts in a brief\n
\n Survey\n .\n
\n \n ',"neutral",!0,0,(()=>{t.dismissedCount+=1,this.saveToStorage(e,t)}));if(r){const o=r.querySelector(".survey-link");o&&o.addEventListener("click",(()=>{t.surveyClickedCount+=1,this.saveToStorage(e,t)}))}}static showToast(e,t="neutral",r=!0,o=3e3,n){const a=document.createElement("div");a.className=`toast ${t}`;const i=document.createElement("button");return i.className="close-btn",i.innerHTML="×",i.onclick=()=>{"function"==typeof n&&n(),a.remove()},a.innerHTML=e,r&&a.appendChild(i),document.getElementById("toaster").appendChild(a),o>0&&setTimeout((()=>{a.remove()}),o),a}static async LogReferral(e=null){const t=e=>new URLSearchParams(window.location.search).get(e);if((()=>{if(!document.referrer)return!1;return new URL(document.referrer).hostname===window.location.hostname})())return;let r={device_uuid:this.getDeviceUuid(),session_uuid:await this.getSessionUuid()};const o=t("utm_source"),n=t("utm_medium"),a=t("utm_campaign"),i=t("utm_term"),s=t("utm_content"),c=t("ref"),d=document.referrer;if(o&&(r.utm_source=o),n&&(r.utm_medium=n),a&&(r.utm_campaign=a),i&&(r.utm_term=i),s&&(r.utm_content=s),d&&(r.referrer_url=d),c&&(r.referral_code=c.slice(0,500)),r.landing_url=window.location.href,d||o||a||c){const t=`referral-logged-${c||"none"}`;if(sessionStorage.getItem(t))return;sessionStorage.setItem(t,"1"),fetch(window.chronoodleConfig.saveReferralEndpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)}).then((e=>e.json())).then((t=>{e&&e(t)})).catch((e=>{console.error("Error logging referral:",e)}))}}static getQueryStringParam(e){return e?new URLSearchParams(window.location.search).get(e):null}static isQueryStringParamPresent(e){return!!e&&null!==this.getQueryStringParam(e)}static async startSession(){let e=this.getFromStorage("sessionUuid",sessionStorage),t=this.getFromStorage("deviceUuid");if(t||(t=`device_${this.generateUuid()}`,this.saveToStorage("deviceUuid",t)),!e){e=`session_${this.generateUuid()}`;const t=(new Date).toISOString();this.saveToStorage("sessionUuid",e,sessionStorage),this.saveToStorage("sessionStartDateTime",t,sessionStorage),this.isBot()||await this.logSessionStart()}return e}static async getSessionUuid(){return await this.startSession()}static async logSessionStart(){const e={environment:this.getEnvironment(),deviceUuid:this.getDeviceUuid(),sessionUuid:await this.getSessionUuid(),deviceInfo:this.getDeviceInfo(),userAgent:navigator.userAgent};await(new OodleApi).post("/api/save-session-data",e)}static getUsernameInitials(){try{const e=this.getUsername().toUpperCase();return e?e.length<2?"":e.substring(0,1):""}catch(e){return"X"}}static getLocalYYYYMMDD(){const e=new Date;return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}static parseLocalDateString(e){const[t,r,o]=e.split("-").map(Number);return new Date(t,r-1,o)}static formatSmartDate(e){if(!e)return null;const t=e instanceof Date?e:this.parseLocalDateString(e),r=new Date,o=(e,t)=>e.getFullYear()===t.getFullYear()&&e.getMonth()===t.getMonth()&&e.getDate()===t.getDate(),n=new Date;return n.setDate(r.getDate()-1),o(t,r)?"TODAY":o(t,n)?"YESTERDAY":t.toLocaleDateString(void 0,{year:"numeric",month:"long",day:"numeric",weekday:"long"})}static getUserStartDate(){const e=this.Jwt.getClaim("createdAt");if(e){const t=Date.parse(e+"Z");if(!isNaN(t))return new Date(t)}return null}static getUsername(){return this.Jwt.getClaim("username")}static saveToStorage(e,t,r=localStorage){if("function"!=typeof r.setItem)throw new Error("Invalid storage provider: must implement setItem");r.setItem(e,JSON.stringify(t))}static getFromStorage(e,t=localStorage){if("function"!=typeof t.getItem)throw new Error("Invalid storage provider: must implement getItem");const r=t.getItem(e);try{return JSON.parse(r)}catch{return r}}static removeFromStorage(e,t=localStorage){if("function"!=typeof t.removeItem)throw new Error("Invalid storage provider: must implement removeItem");try{t.removeItem(e)}catch{return!1}return!0}static clearLocalStorageByPrefix(e){if("string"==typeof e&&""!==e.trim())for(const t in localStorage)t.startsWith(e)&&localStorage.removeItem(t);else console.warn("clearLocalStorageByPrefix: invalid prefix provided")}static saveToStorageWithExpiry(e,t,r){const o={value:t,expiry:(new Date).getTime()+r};this.saveToStorage(e,o)}static getFromStorageWithExpiry(e){const t=this.getFromStorage(e);if(!t)return null;return(new Date).getTime()>t.expiry?(this.removeFromStorage(e),null):t.value}static getDeviceUuid(){let e=this.getFromStorage("deviceUuid");return e||(e=`device_${this.generateUuid()}`,this.saveToStorage("deviceUuid",e)),e}static getEnvironment(){return window.chronoodleConfig.environment.toUpperCase()}static getDeviceInfo(){const e=navigator.platform;let t="Unknown OS";/Android/.test(navigator.userAgent)?t="Android":/iPhone|iPad|iPod/.test(navigator.userAgent)?t="iOS":e.includes("Mac")?t="MacOS":e.includes("Win")?t="Windows":e.includes("Linux")&&(t="Linux");const r=navigator.userAgent;let o="Unknown Browser";r.includes("Chrome")&&!r.includes("Chromium")?o="Chrome "+r.match(/Chrome\/(\d+\.\d+)/)[1]:r.includes("Firefox")?o="Firefox "+r.match(/Firefox\/(\d+\.\d+)/)[1]:r.includes("Safari")&&!r.includes("Chrome")?o="Safari "+r.match(/Version\/(\d+\.\d+)/)[1]:r.includes("MSIE")||r.includes("Trident")?o="Internet Explorer":r.includes("Edg")&&(o="Edge "+r.match(/Edg\/(\d+\.\d+)/)[1]);return`${t} | ${o} | ${/Mobi|Android/i.test(r)?"Mobile":"Desktop"} | ${`${window.screen.width}x${window.screen.height}`} | ${Intl.DateTimeFormat().resolvedOptions().timeZone} | ${navigator.language||navigator.userLanguage}`}static generateUuid(){return"undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID?crypto.randomUUID():([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,(e=>(e^crypto.getRandomValues(new Uint8Array(1))[0]&15>>e/4).toString(16)))}static isBot(){const e=navigator.userAgent.toLowerCase();return!!["bot","crawl","spider","slurp","mediapartners","googlebot","bingbot","baiduspider","yandex","duckduckbot","facebot","ia_archiver"].some((t=>e.includes(t)))||(!!navigator.webdriver||(0===window.screen.width||0===window.screen.height))}static mergeUniqueInArray(e,t){return[...new Set([...e,...t])]}static toggleDebugMode(){const e=document.getElementById("debug");e.classList.contains("open")?e.classList.remove("open"):e.classList.add("open")}static getFeatures(){const e=this.getFromStorage("featureFlags")||[],t=[],r=["enabled"],o=[{name:"'You Are Here' Mode",code:"you_are_here_mode",description:"Adds a visual callout to the 'Now' label in the game.",enabled:!1,rendered:!0,deletable:!1},{name:"Time Flip (Early Access)",code:"time_flip_mode",description:"Flips the chronological display order. When enabled, 'The Big Bang' will be at the top and 'Now' goes to the bottom.",enabled:!1,rendered:!0,deletable:!1},{name:"User Accounts",code:"user_accounts",description:"Sign in and save progress to your Oodle Games account",enabled:!0,rendered:!1,deletable:!1}];o.forEach((e=>{e.rendered||t.push(e.code)}));const n=e.filter((e=>!t.includes(e.code)));return o.forEach((e=>{const t=n.find((t=>t.code===e.code));t&&e.rendered?Object.keys(e).forEach((o=>{r.includes(o)||(t[o]=e[o])})):n.push(e)})),n.sort(((e,t)=>{const r=e.name.replace(/^[^a-zA-Z0-9]+/,"").toLowerCase(),o=t.name.replace(/^[^a-zA-Z0-9]+/,"").toLowerCase();return r.localeCompare(o)})),this.saveToStorage("featureFlags",n),n}static isFeatureAdded(e){return(this.getFromStorage("featureFlags")||[]).some((t=>t.code===e))}static disableFeature(e){let t=this.getFromStorage("featureFlags")||[];const r=t.findIndex((t=>t.code===e));-1!==r&&(t[r].enabled=!1,this.saveToStorage("featureFlags",t)),document.dispatchEvent(new Event("featureChange")),this.addTelemetry("FEATURE_FLAG",{code:e,enabled:!1})}static enableFeature(e){let t=this.getFromStorage("featureFlags")||[];const r=t.findIndex((t=>t.code===e));-1!==r&&(t[r].enabled=!0),this.saveToStorage("featureFlags",t),document.dispatchEvent(new Event("featureChange")),this.addTelemetry("FEATURE_FLAG",{code:e,enabled:!0})}static removeFeature(e){let t=this.getFromStorage("featureFlags")||[];t=t.filter((t=>t.code!==e)),document.dispatchEvent(new Event("featureChange")),this.saveToStorage("featureFlags",t)}static isFeatureEnabled(e){return(this.getFromStorage("featureFlags")||[]).some((t=>t.code===e&&t.enabled))}static async loadFeaturesBySecret(e){const t=await(new OodleApi).post("/api/v1/feature/get-by-secret",{secret:e});if(t.success&&t.data&&Array.isArray(t.data.features)&&t.data.features.length>0){const e=t.data.features,r=this.getFromStorage("featureFlags")||[];return e.forEach((e=>{r.find((t=>t.code===e.code))||r.push(e)})),this.saveToStorage("featureFlags",r),r}return null}static async addTelemetry(e,t){const r="undefined"!=typeof chronoodle,o=r&&chronoodle.currentChallengeKey?chronoodle.currentChallengeKey:null,n=r&&chronoodle.currentChallenge?String(chronoodle.currentChallenge.gameId):null,a=r&&chronoodle.getGameStateText?chronoodle.getGameStateText():null,i={environment:this.getEnvironment(),deviceUuid:this.getDeviceUuid(),sessionUuid:await this.getSessionUuid(),gameKey:o,gameId:n,eventType:e,gameData:t,gameState:a};await(new OodleApi).enqueuePost("/api/save-game-data",i)}static setCookie(e,t,r={}){let o=`${encodeURIComponent(e)}=${encodeURIComponent(t)}`;if(r.expires)if("number"===r.expires){const e=new Date;e.setTime(e.getTime()+1e3*r.expires),o+=`; expires=${e.toUTCString()}`}else r.expires instanceof Date&&(o+=`; expires=${r.expires.toUTCString()}`);r.path&&(o+=`; path=${r.path}`),r.domain&&(o+=`; domain=${r.domain}`),r.secure&&(o+="; secure"),r.sameSite&&(o+=`; SameSite=${r.sameSite}`),document.cookie=o}static getCookie(e){return document.cookie.split("; ").reduce(((e,t)=>{const[r,o]=t.split("=");return e[decodeURIComponent(r)]=decodeURIComponent(o),e}),{})[e]||null}static deleteCookie(e,t={}){let r=`${encodeURIComponent(e)}=; expires=Thu, 01 Jan 1970 00:00:00 GMT`;t.path&&(r+=`; path=${t.path}`),t.domain&&(r+=`; domain=${t.domain}`),document.cookie=r}static createScrim(e=3){const t=document.createElement("div");return t.setAttribute("class","basic-scrim"),t.style.zIndex=e,document.body.appendChild(t),t}}"undefined"!=typeof module&&void 0!==module.exports&&(module.exports=Utils)- 7 moments. 1 timeline.
- Put them in the correct order.
- Perfect Games
- Correct Answers
- Games Played
Impersonating: @hoodler

DEBUG MODE You can re-enable debug mode in Settings.