1/*! @preserve Third-party software notices: /legal/THIRD_PARTY_NOTICES.txt; asset licenses: /legal/ASSET_LICENSES.txt; CycloneDX SBOM: /legal/sbom.cdx.json */ 2import{STORAGE_KEYS as e,VARIANT_STORAGE_KEYS as t}from"./constants.ClziSW2j.js";import{readLocal as n}from"./browser-state-gateway.C2b19Lbh.js";import{appendProgressEvent as r,createProgressStartEvent as i,createProgressTerminalEvent as a,readProgressLedger as o}from"./progressLedger.CJTDewRD.js";function s(e,t){if(e===`klondike`){let e=`klondike:${t?.drawMode??1}`;return t?.tier===void 0?e:t.tierVersion===2||t.tierVersion===3?`${e}:v${t.tierVersion}:${t.tier}`:`${e}:${t.tier}`}return e===`spider`?`spider:${t?.suitMode??1}`:e}function c(){return{played:0,wins:0,bestTimeMs:null,bestMoves:null,currentStreak:0,longestStreak:0,lastPlayedDealId:null,lastWonDealId:null}}function l(e){if(!e||typeof e!=`object`)return null;let t=e;return typeof t.played!=`number`||typeof t.wins!=`number`||typeof t.currentStreak!=`number`||typeof t.longestStreak!=`number`?null:{played:t.played,wins:t.wins,bestTimeMs:typeof t.bestTimeMs==`number`?t.bestTimeMs:null,bestMoves:typeof t.bestMoves==`number`?t.bestMoves:null,currentStreak:t.currentStreak,longestStreak:t.longestStreak,lastPlayedDealId:typeof t.lastPlayedDealId==`string`?t.lastPlayedDealId:null,lastWonDealId:typeof t.lastWonDealId==`string`?t.lastWonDealId:null}}function u(e){if(!e)return null;try{let t=JSON.parse(e);if(!t||typeof t!=`object`)return null;let n=t;if(n.v!==1||!n.games||typeof n.games!=`object`)return null;let r={};for(let[e,t]of Object.entries(n.games)){let n=l(t);n&&(r[e]=n)}return{v:1,games:r}}catch{return null}}function d(){return u(n(e.STATS_LIFETIME))}function f(e,t){let n=t>>>0;for(let t=0;t<e.length;t+=1)n^=e.charCodeAt(t),n=Math.imul(n,16777619);return n>>>0}function p(n,r){let i;if(n.variant===`klondike`)i=n.drawMode===2?[e.GAME_DRAW2]:n.mode===`turn3`?[e.GAME_TURN3,e.GAME_TURN3_LEGACY]:[e.GAME];else if(n.variant===`spider`)i=n.suitMode===2?[e.GAME_SPIDER_2]:n.suitMode===4?[e.GAME_SPIDER_4]:[e.GAME_SPIDER];else{let e=t[n.variant];i=e?[e]:[]}let a=[`yukon`,`russian`,`alaska`,`scorpion`,`wasp`].includes(n.variant)?n.variant:``;return i.map(e=>{let t=[e,n.variant,`${n.variant}-rules-v1`,r,``,n.drawMode??``,n.suitMode??``,a].join(`|`);return`ps_d_${f(t,2166136261).toString(16).padStart(8,`0`)}${f(t,2654435769).toString(16).padStart(8,`0`)}`})}function m(e,t){if(e===t.dealId)return!0;let n=/^(\d+):(\d+)$/u.exec(e);if(!n)return!1;let r=Number(n[1]);return Number.isSafeInteger(r)&&r>=0&&p(t,r).includes(t.dealId)}function h(e,t){return e===null?t:t===null?e:Math.min(e,t)}function g(e){let t=[...e.baseline?[{capturedAt:e.baseline.capturedAt,raw:e.baseline.lifetimeStatsRaw}]:[],...(e.accountBaselines??[]).map(e=>({capturedAt:e.capturedAt,raw:e.lifetimeStatsRaw}))],n={},r=new Map,i=null;for(let e of t){i=i===null?e.capturedAt:Math.max(i,e.capturedAt);let t=u(e.raw);for(let[i,a]of Object.entries(t?.games??{})){let t=n[i];if(!t){n[i]={...a},r.set(i,e.capturedAt);continue}let o=e.capturedAt>=(r.get(i)??0);n[i]={played:t.played+a.played,wins:t.wins+a.wins,bestTimeMs:h(t.bestTimeMs,a.bestTimeMs),bestMoves:h(t.bestMoves,a.bestMoves),currentStreak:Math.max(t.currentStreak,a.currentStreak),longestStreak:Math.max(t.longestStreak,a.longestStreak),lastPlayedDealId:o?a.lastPlayedDealId:t.lastPlayedDealId,lastWonDealId:o?a.lastWonDealId:t.lastWonDealId},o&&r.set(i,e.capturedAt)}}return{stats:Object.keys(n).length>0?{v:1,games:n}:null,capturedAt:i}}function _(e){let t=g(e),n=t.stats;if(!n&&e.events.length===0)return null;let r={};for(let[e,t]of Object.entries(n?.games??{}))r[e]={...t};let i=new Map;for(let t of e.events)t.mode!==`daily`&&t.phase===`start`&&i.set(t.attemptId,{attemptId:t.attemptId,dealId:t.dealId,bucket:t.bucket,variant:t.variant,mode:t.mode,occurredAt:t.occurredAt,startEventId:t.eventId,drawMode:t.drawMode,suitMode:t.suitMode});for(let t of e.events){if(t.mode===`daily`||t.phase!==`terminal`)continue;let e=i.get(t.attemptId);e&&(e.terminal={outcome:t.outcome,moves:t.moves,playedMs:t.playedMs})}let a=Array.from(i.values()).sort((e,t)=>
2e.occurredAt-t.occurredAt||e.startEventId.localeCompare(t.startEventId));for(let e of a){let t=r[e.bucket]?{...r[e.bucket]}:c();t.lastPlayedDealId!==null&&t.lastPlayedDealId!==t.lastWonDealId&&!m(t.lastPlayedDealId,e)&&(t.currentStreak=0),t.played+=1,t.lastPlayedDealId=e.dealId,e.terminal?.outcome===`won`&&(t.wins+=1,t.bestTimeMs=t.bestTimeMs===null?e.terminal.playedMs:Math.min(t.bestTimeMs,e.terminal.playedMs),t.bestMoves=t.bestMoves===null?e.terminal.moves:Math.min(t.bestMoves,e.terminal.moves),t.currentStreak+=1,t.longestStreak=Math.max(t.longestStreak,t.currentStreak),t.lastWonDealId=e.dealId),r[e.bucket]=t}return{v:2,historicalBaselineCapturedAt:t.capturedAt,games:r}}function v(e){let t=_(e);return t?{v:1,games:Object.fromEntries(Object.entries(t.games).map(([e,t])=>[e,{...t}]))}:null}function y(e,t){return _(e)?.games[t]??null}async function b(e){let t=_(await o(e));if(t||e)return t;let n=d();return n?{v:2,historicalBaselineCapturedAt:null,games:n.games}:null}async function x(e,t){return(await b(t))?.games[e]??null}async function S(e,t,n){let a=await r(i({...t,bucket:e,firstAction:t.firstAction}),n,t.rankingDeal);return{...a,counted:a.created,stats:(a.afterSnapshot?y(a.afterSnapshot,e):await x(e,n))??c()}}async function C(e,t,n,i){let o=await r(a({...t,bucket:e,outcome:`won`,playedMs:n.ms,moves:n.moves,reason:n.reason}),i,t.rankingDeal),s=o.beforeSnapshot?y(o.beforeSnapshot,e):await x(e,i),l=o.afterSnapshot?y(o.afterSnapshot,e):await x(e,i),u=o.created;return{...o,stats:l??s??c(),credited:u,newBestTime:u&&(s?.bestTimeMs===null||s?.bestTimeMs===void 0||n.ms<s.bestTimeMs),newBestMoves:u&&(s?.bestMoves===null||s?.bestMoves===void 0||n.moves<s.bestMoves)}}async function w(e,t,n,i){let o=await r(a({...t,bucket:e,outcome:n.outcome,playedMs:n.ms,moves:n.moves,reason:n.reason}),i,t.rankingDeal);return{...o,recorded:o.created,stats:(o.afterSnapshot?y(o.afterSnapshot,e):await x(e,i))??c()}}export{v as projectLifetimeStatsV1,b as readLifetimeStatsV2,x as readVariantStatsV2,S as recordGamePlayedV2,w as recordGameTerminalV2,C as recordWinV2,s as statsKeyFor};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.