update
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
/** Base simultaneous opens at key 1 (x10). Each +1 key adds +1 open until x20, then continues +1 per key. */
|
||||
export const BASE_MAX_OPENS = 10;
|
||||
|
||||
/** Keys 1–10 → next key always costs this many opens. */
|
||||
export const OPENS_PER_KEY_EARLY = 100;
|
||||
|
||||
/** From key 11 onward: cost = OPENS_PER_KEY_EARLY × (keys - 9). */
|
||||
export const ESCALATION_KEY_THRESHOLD = 11;
|
||||
|
||||
export function maxOpensForKeys(keys) {
|
||||
const k = Math.max(1, keys);
|
||||
return k + (BASE_MAX_OPENS - 1);
|
||||
}
|
||||
|
||||
export function opensRequiredForNextKey(keys, keyOpenReduction = 0) {
|
||||
const k = Math.max(1, keys);
|
||||
const base =
|
||||
k < ESCALATION_KEY_THRESHOLD
|
||||
? OPENS_PER_KEY_EARLY
|
||||
: OPENS_PER_KEY_EARLY * (k - (ESCALATION_KEY_THRESHOLD - 2));
|
||||
const reduction = Math.max(0, Number(keyOpenReduction) || 0);
|
||||
return Math.max(1, base - reduction);
|
||||
}
|
||||
|
||||
export function serializeKeyProgress(progress, keyOpenReduction = 0) {
|
||||
const keys = progress?.keys ?? 1;
|
||||
const opensSinceLastKey = progress?.opensSinceLastKey ?? 0;
|
||||
const totalOpens = progress?.totalOpens ?? 0;
|
||||
const opensRequired = opensRequiredForNextKey(keys, keyOpenReduction);
|
||||
return {
|
||||
keys,
|
||||
maxOpens: maxOpensForKeys(keys),
|
||||
opensSinceLastKey,
|
||||
opensRequired,
|
||||
totalOpens,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply opens to progress state. Returns updated fields + keysGained.
|
||||
*/
|
||||
export function applyOpens(progress, count, keyOpenReduction = 0) {
|
||||
let keys = Math.max(1, progress.keys ?? 1);
|
||||
let opensSinceLastKey = progress.opensSinceLastKey ?? 0;
|
||||
let totalOpens = progress.totalOpens ?? 0;
|
||||
let keysGained = 0;
|
||||
|
||||
opensSinceLastKey += count;
|
||||
totalOpens += count;
|
||||
|
||||
while (opensSinceLastKey >= opensRequiredForNextKey(keys, keyOpenReduction)) {
|
||||
opensSinceLastKey -= opensRequiredForNextKey(keys, keyOpenReduction);
|
||||
keys += 1;
|
||||
keysGained += 1;
|
||||
}
|
||||
|
||||
return { keys, opensSinceLastKey, totalOpens, keysGained };
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild keys/opensSinceLastKey from a lifetime open count (backfill).
|
||||
* Prestige reduction is ignored here — backfill uses base costs.
|
||||
*/
|
||||
export function progressFromTotalOpens(totalOpens) {
|
||||
let keys = 1;
|
||||
let remaining = totalOpens;
|
||||
|
||||
while (remaining >= opensRequiredForNextKey(keys, 0)) {
|
||||
remaining -= opensRequiredForNextKey(keys, 0);
|
||||
keys += 1;
|
||||
}
|
||||
|
||||
return {
|
||||
keys,
|
||||
opensSinceLastKey: remaining,
|
||||
totalOpens,
|
||||
};
|
||||
}
|
||||
|
||||
export async function getOrCreateProgress(tx, userId, caseId) {
|
||||
const existing = await tx.caseKeyProgress.findUnique({
|
||||
where: { userId_caseId: { userId, caseId } },
|
||||
});
|
||||
if (existing) return existing;
|
||||
|
||||
return tx.caseKeyProgress.create({
|
||||
data: { userId, caseId, keys: 1, opensSinceLastKey: 0, totalOpens: 0 },
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user