chore: use ideal time when going backwards to satisfy constraints #2438

Merged
Sainan merged 1 commits from time-constraint-redux into main 2025-07-08 20:50:11 -07:00

View File

@ -1033,75 +1033,124 @@ const pushVoidStorms = (arr: IVoidStorm[], hour: number): void => {
} }
}; };
const doesTimeSatsifyConstraints = (timeSecs: number): boolean => { interface ITimeConstraint {
if (config.worldState?.eidolonOverride) { //name: string;
isValidTime: (timeSecs: number) => boolean;
getIdealTimeBefore: (timeSecs: number) => number;
}
const eidolonDayConstraint: ITimeConstraint = {
//name: "eidolon day",
isValidTime: (timeSecs: number): boolean => {
const eidolonEpoch = 1391992660; const eidolonEpoch = 1391992660;
const eidolonCycle = Math.trunc((timeSecs - eidolonEpoch) / 9000); const eidolonCycle = Math.trunc((timeSecs - eidolonEpoch) / 9000);
const eidolonCycleStart = eidolonEpoch + eidolonCycle * 9000; const eidolonCycleStart = eidolonEpoch + eidolonCycle * 9000;
const eidolonCycleEnd = eidolonCycleStart + 9000; const eidolonCycleEnd = eidolonCycleStart + 9000;
const eidolonCycleNightStart = eidolonCycleEnd - 3000; const eidolonCycleNightStart = eidolonCycleEnd - 3000;
if (config.worldState.eidolonOverride == "day") { return !isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, eidolonCycleNightStart * 1000);
if ( },
//timeSecs < eidolonCycleStart || getIdealTimeBefore: (timeSecs: number): number => {
isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, eidolonCycleNightStart * 1000) const eidolonEpoch = 1391992660;
) { const eidolonCycle = Math.trunc((timeSecs - eidolonEpoch) / 9000);
return false; const eidolonCycleStart = eidolonEpoch + eidolonCycle * 9000;
} return eidolonCycleStart;
} else {
if (
timeSecs < eidolonCycleNightStart ||
isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, eidolonCycleEnd * 1000)
) {
return false;
}
}
} }
};
if (config.worldState?.vallisOverride) { const eidolonNightConstraint: ITimeConstraint = {
//name: "eidolon night",
isValidTime: (timeSecs: number): boolean => {
const eidolonEpoch = 1391992660;
const eidolonCycle = Math.trunc((timeSecs - eidolonEpoch) / 9000);
const eidolonCycleStart = eidolonEpoch + eidolonCycle * 9000;
const eidolonCycleEnd = eidolonCycleStart + 9000;
const eidolonCycleNightStart = eidolonCycleEnd - 3000;
return (
timeSecs >= eidolonCycleNightStart &&
!isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, eidolonCycleEnd * 1000)
);
},
getIdealTimeBefore: (timeSecs: number): number => {
const eidolonEpoch = 1391992660;
const eidolonCycle = Math.trunc((timeSecs - eidolonEpoch) / 9000);
const eidolonCycleStart = eidolonEpoch + eidolonCycle * 9000;
const eidolonCycleEnd = eidolonCycleStart + 9000;
const eidolonCycleNightStart = eidolonCycleEnd - 3000;
if (eidolonCycleNightStart > timeSecs) {
// Night hasn't started yet, but we need to return a time in the past.
return eidolonCycleNightStart - 9000;
}
return eidolonCycleNightStart;
}
};
const venusColdConstraint: ITimeConstraint = {
//name: "venus cold",
isValidTime: (timeSecs: number): boolean => {
const vallisEpoch = 1541837628; const vallisEpoch = 1541837628;
const vallisCycle = Math.trunc((timeSecs - vallisEpoch) / 1600); const vallisCycle = Math.trunc((timeSecs - vallisEpoch) / 1600);
const vallisCycleStart = vallisEpoch + vallisCycle * 1600; const vallisCycleStart = vallisEpoch + vallisCycle * 1600;
const vallisCycleEnd = vallisCycleStart + 1600; const vallisCycleEnd = vallisCycleStart + 1600;
const vallisCycleColdStart = vallisCycleStart + 400; const vallisCycleColdStart = vallisCycleStart + 400;
if (config.worldState.vallisOverride == "cold") { return (
if ( timeSecs >= vallisCycleColdStart &&
timeSecs < vallisCycleColdStart || !isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, vallisCycleEnd * 1000)
isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, vallisCycleEnd * 1000) );
) { },
return false; getIdealTimeBefore: (timeSecs: number): number => {
} const vallisEpoch = 1541837628;
} else { const vallisCycle = Math.trunc((timeSecs - vallisEpoch) / 1600);
if ( const vallisCycleStart = vallisEpoch + vallisCycle * 1600;
//timeSecs < vallisCycleStart || const vallisCycleColdStart = vallisCycleStart + 400;
isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, vallisCycleColdStart * 1000) if (vallisCycleColdStart > timeSecs) {
) { // Cold hasn't started yet, but we need to return a time in the past.
return false; return vallisCycleColdStart - 1600;
}
return vallisCycleColdStart;
}
};
const venusWarmConstraint: ITimeConstraint = {
//name: "venus warm",
isValidTime: (timeSecs: number): boolean => {
const vallisEpoch = 1541837628;
const vallisCycle = Math.trunc((timeSecs - vallisEpoch) / 1600);
const vallisCycleStart = vallisEpoch + vallisCycle * 1600;
const vallisCycleColdStart = vallisCycleStart + 400;
return !isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, vallisCycleColdStart * 1000);
},
getIdealTimeBefore: (timeSecs: number): number => {
const vallisEpoch = 1541837628;
const vallisCycle = Math.trunc((timeSecs - vallisEpoch) / 1600);
const vallisCycleStart = vallisEpoch + vallisCycle * 1600;
return vallisCycleStart;
}
};
const getIdealTimeSatsifyingConstraints = (constraints: ITimeConstraint[]): number => {
let timeSecs = Math.trunc(Date.now() / 1000);
let allGood;
do {
allGood = true;
for (const constraint of constraints) {
if (!constraint.isValidTime(timeSecs)) {
//logger.debug(`${constraint.name} is not happy with ${timeSecs}`);
const prevTimeSecs = timeSecs;
const suggestion = constraint.getIdealTimeBefore(timeSecs);
timeSecs = suggestion;
do {
timeSecs += 60;
if (timeSecs >= prevTimeSecs || !constraint.isValidTime(timeSecs)) {
timeSecs = suggestion; // Can't find a compromise; just take the suggestion and try to compromise on another constraint.
break;
}
} while (!constraints.every(constraint => constraint.isValidTime(timeSecs)));
allGood = false;
break;
} }
} }
} } while (!allGood);
return timeSecs;
if (config.worldState?.duviriOverride) {
const duviriMoods = ["sorrow", "fear", "joy", "anger", "envy"];
const desiredMood = duviriMoods.indexOf(config.worldState.duviriOverride);
if (desiredMood == -1) {
logger.warn(`ignoring invalid config value for worldState.duviriOverride`, {
value: config.worldState.duviriOverride,
valid_values: duviriMoods
});
} else {
const moodIndex = Math.trunc(timeSecs / 7200);
const moodStart = moodIndex * 7200;
const moodEnd = moodStart + 7200;
if (
moodIndex % 5 != desiredMood ||
isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, moodEnd * 1000)
) {
return false;
}
}
}
return true;
}; };
const getVarziaRotation = (week: number): string => { const getVarziaRotation = (week: number): string => {
@ -1179,10 +1228,38 @@ const getAllVarziaManifests = (): IPrimeVaultTraderOffer[] => {
}; };
export const getWorldState = (buildLabel?: string): IWorldState => { export const getWorldState = (buildLabel?: string): IWorldState => {
let timeSecs = Math.round(Date.now() / 1000); const constraints: ITimeConstraint[] = [];
while (!doesTimeSatsifyConstraints(timeSecs)) { if (config.worldState?.eidolonOverride) {
timeSecs -= 60; constraints.push(config.worldState.eidolonOverride == "day" ? eidolonDayConstraint : eidolonNightConstraint);
} }
if (config.worldState?.vallisOverride) {
constraints.push(config.worldState.vallisOverride == "cold" ? venusColdConstraint : venusWarmConstraint);
}
if (config.worldState?.duviriOverride) {
const duviriMoods = ["sorrow", "fear", "joy", "anger", "envy"];
const desiredMood = duviriMoods.indexOf(config.worldState.duviriOverride);
if (desiredMood == -1) {
logger.warn(`ignoring invalid config value for worldState.duviriOverride`, {
value: config.worldState.duviriOverride,
valid_values: duviriMoods
});
} else {
constraints.push({
//name: `duviri ${config.worldState.duviriOverride}`,
isValidTime: (timeSecs: number): boolean => {
const moodIndex = Math.trunc(timeSecs / 7200);
return moodIndex % 5 == desiredMood;
},
getIdealTimeBefore: (timeSecs: number): number => {
let moodIndex = Math.trunc(timeSecs / 7200);
moodIndex -= ((moodIndex % 5) - desiredMood + 5) % 5; // while (moodIndex % 5 != desiredMood) --moodIndex;
const moodStart = moodIndex * 7200;
return moodStart;
}
});
}
}
const timeSecs = getIdealTimeSatsifyingConstraints(constraints);
const timeMs = timeSecs * 1000; const timeMs = timeSecs * 1000;
const day = Math.trunc((timeMs - EPOCH) / 86400000); const day = Math.trunc((timeMs - EPOCH) / 86400000);
const week = Math.trunc(day / 7); const week = Math.trunc(day / 7);