docs: inventory removable Ref compatibility shims

This commit is contained in:
2026-08-07 06:12:00 +00:00
parent e198f70756
commit d0789f20e9
17 changed files with 293 additions and 0 deletions
@@ -25,7 +25,9 @@ interface ProcureContext<
const ACTION_NAME = '물자조달';
const ACTION_KEY = 'che_물자조달';
// REF-COMPAT:BEGIN ref-int-column-write-rounding
export const roundLegacyAccumulatedInteger = (current: number, delta: number): number => Math.round(current + delta);
// REF-COMPAT:END ref-int-column-write-rounding
export const resolveLegacyExperienceLevel = (experience: number): number =>
Math.max(
@@ -60,12 +60,14 @@ const DEFAULT_MIN_POP = 30000;
const DEFAULT_TRUST = 50;
const MIN_CREW = 100;
// REF-COMPAT:BEGIN ref-php-half-rounding
// PHP round() compensates for the small binary drift around a half boundary.
// Ref then converts the result to int through Util::round().
export const roundLegacyRecruitCost = (value: number): number => {
const corrected = value + Math.sign(value) * Number.EPSILON * Math.max(1, Math.abs(value));
return corrected < 0 ? Math.ceil(corrected - 0.5) : Math.floor(corrected + 0.5);
};
// REF-COMPAT:END ref-php-half-rounding
export const ARGS_SCHEMA = z.preprocess(
(raw) => {
@@ -5,6 +5,8 @@
*/
import { readLegacyStoredFloat, toLegacyStoredFloat } from '@sammo-ts/logic/compat/legacyFloat.js';
// REF-COMPAT:BEGIN ref-mariadb-float-boundary
export const storeLegacyCityTrust = (value: number): number => toLegacyStoredFloat(value);
export const readLegacyCityTrust = (value: number): number => readLegacyStoredFloat(value);
// REF-COMPAT:END ref-mariadb-float-boundary
@@ -1,3 +1,5 @@
// REF-COMPAT:BEGIN ref-stat-injury-truncation
export const applyLegacyInjury = (value: number, injury: number): number => value * ((100 - injury) / 100);
export const finalizeLegacyStat = (value: number): number => Math.trunc(value);
// REF-COMPAT:END ref-stat-injury-truncation
+2
View File
@@ -1,3 +1,4 @@
// REF-COMPAT:BEGIN ref-mariadb-float-boundary
// MariaDB FLOAT stores binary32, but its text protocol exposes only six
// significant decimal digits. Ref reads that text into PHP before every
// command/battle update, so both boundaries are part of the game state.
@@ -27,3 +28,4 @@ export const readLegacyStoredFloat = (value: number): number => {
export const addLegacyStoredFloat = (current: number, delta: number): number =>
toLegacyStoredFloat(readLegacyStoredFloat(current) + delta);
// REF-COMPAT:END ref-mariadb-float-boundary
+4
View File
@@ -50,12 +50,14 @@ const findReport = (reports: WarUnitReport[], predicate: (report: WarUnitReport)
const getDeadCounter = (city: City): number => getMetaNumber(city.meta, META_DEAD, 0);
// REF-COMPAT:BEGIN ref-dead-split-int-binding
const increaseDeadCounter = (city: City, delta: number): void => {
// Ref binds each `dead + %i` increment as an integer before MariaDB adds
// it. Truncate each 40/60 percent split independently; rounding the
// accumulated counter changes monthly recovery and war income.
city.meta[META_DEAD] = getDeadCounter(city) + Math.trunc(delta);
};
// REF-COMPAT:END ref-dead-split-int-binding
const isSupplyCity = (city: City): boolean => {
const raw = city.meta.supply;
@@ -127,9 +129,11 @@ const applyNationTechGain = <TriggerState extends GeneralTriggerState>(
const divisor = Math.max(config.initialNationGenLimit, total);
const currentTech = getMetaNumber(nation.meta, 'tech', 0);
const delta = gain / divisor;
// REF-COMPAT:BEGIN ref-mariadb-float-boundary
// Ref executes `tech + delta` inside MariaDB for battle gains, so the
// arithmetic starts from the stored binary32 value without a PHP text read.
nation.meta.tech = Math.fround(currentTech + delta);
// REF-COMPAT:END ref-mariadb-float-boundary
if ((process.env.CORE_WAR_TECH_TRACE_NATION_IDS?.split(',') ?? []).includes(String(nation.id))) {
process.stdout.write(
`WAR_TECH_TRACE ${JSON.stringify({ engine: 'core', nationId: nation.id, side: context.side, currentTech, baseGain, gain, total, effective, divisor, delta, storedTech: nation.meta.tech, attackerGeneralId: context.attackerReport.id })}\n`
+2
View File
@@ -390,10 +390,12 @@ export class WarUnitGeneral<
nextExp *= 0.9;
}
const adjustedExp = this.actionPipeline.onCalcStat(this.getActionContext(), 'addDex', nextExp, { armType });
// REF-COMPAT:BEGIN ref-meekrodb-sql-precision
// PHP interpolates floats into MeekroDB SQL with precision=14 before
// MariaDB rounds the integer dex column. Normalize this accumulated
// battle value at the same boundary (for example ...499999999996 -> .5).
this.general.meta[key] = Number((base + adjustedExp).toPrecision(14));
// REF-COMPAT:END ref-meekrodb-sql-precision
}
public calcRiceConsumption(damage: number): number {
+2
View File
@@ -11,6 +11,7 @@ export const clampMin = (value: number, min: number): number => (value < min ? m
export const clampMax = (value: number, max: number): number => (value > max ? max : value);
// REF-COMPAT:BEGIN ref-php-half-rounding
// PHP's round() compensates for small binary floating-point drift around a
// half boundary and rounds halves away from zero. War state is persisted to
// integer columns through legacy Util::round(), so Math.round() is not enough:
@@ -28,6 +29,7 @@ export const round = (value: number): number => {
const corrected = value + Math.sign(value) * Number.EPSILON * Math.max(1, Math.abs(value)) * 4;
return corrected < 0 ? Math.ceil(corrected - 0.5) : Math.floor(corrected + 0.5);
};
// REF-COMPAT:END ref-php-half-rounding
export const getMetaNumber = (meta: Record<string, TriggerValue>, key: string, fallback = 0): number => {
const value = meta[key];