refactor(logic): 과도한 수치 호환 보정을 제거한다

Core 수치 상태는 JavaScript와 PostgreSQL의 자연 정밀도를 유지한다. 정수 상태 경계와 절삭, 수입 배분 및 사망자 분할 순서는 보존한다.
This commit is contained in:
2026-08-24 19:17:06 +00:00
parent fc9fa0c9a6
commit 60dcf815ea
32 changed files with 148 additions and 522 deletions
@@ -1,7 +1,7 @@
import { describe, expect, it } from 'vitest';
import { LogCategory, LogFormat, LogScope, type City, type MapDefinition, type Nation } from '@sammo-ts/logic';
import { createIncomeHandler, resolveLegacyIncomeCityTrust } from '../src/turn/incomeHandler.js';
import { createIncomeHandler, resolveIncomeCityTrust } from '../src/turn/incomeHandler.js';
import { InMemoryTurnWorld } from '../src/turn/inMemoryWorld.js';
import { calculateNpcNationFinance } from '../src/turn/npcTaxHandler.js';
import {
@@ -146,8 +146,8 @@ const buildWorld = (
};
describe('core monthly event actions at the real month boundary', () => {
it('reads income trust through the PHP six-significant-digit FLOAT representation', () => {
expect(resolveLegacyIncomeCityTrust(98.12674)).toBe(98.1267);
it('uses the full-precision trust value for income', () => {
expect(resolveIncomeCityTrust(98.12674)).toBe(98.12674);
});
it('preserves notice format, NewYear month log, age/belong, and officer lock reset', async () => {
@@ -392,7 +392,8 @@ describe('monthly event pipeline', () => {
wall: 81,
meta: { trade: 100, marker: 1 },
});
expect(damagedCity?.meta.trust).toBe(Math.fround(79.6));
expect(damagedCity?.meta.trust).toBe(79.60000000000001);
expect(damagedCity?.meta.trust).not.toBe(Math.fround(79.60000000000001));
expect(world.getGeneralById(1)).toMatchObject({ injury: 0, crew: 99, atmos: 50, train: 51 });
expect(world.getGeneralById(2)).toMatchObject({ injury: 7, crew: 97, atmos: 49, train: 50 });
expect(world.getGeneralById(3)).toMatchObject({ injury: 80, crew: 97, atmos: 49, train: 50 });
@@ -8,7 +8,7 @@ import {
createMonthlyNationCountHandler,
createMonthlyNationStatsHandler,
createMonthlyWarSettingHandler,
roundLegacyNationPowerValue,
roundNationPowerValue,
} from '../src/turn/monthlyNationStatsHandler.js';
import type { TurnGeneral, TurnWorldSnapshot, TurnWorldState } from '../src/turn/types.js';
@@ -108,8 +108,8 @@ const buildNation = (
});
describe('monthly nation statistics boundary', () => {
it('stabilizes MariaDB decimal half boundaries before rounding', () => {
expect(roundLegacyNationPowerValue(342.49999999999994)).toBe(343);
it('uses the native integer boundary for nation power', () => {
expect(roundNationPowerValue(342.49999999999994)).toBe(342);
});
it('matches the fixed legacy power, maxima, war-setting count, and final general cache', async () => {
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest';
import type { City, Nation, NationTraitModule } from '@sammo-ts/logic';
import { InMemoryTurnWorld } from '../src/turn/inMemoryWorld.js';
import { createProcessSemiAnnualHandler, storeLegacySemiAnnualTrust } from '../src/turn/monthlySemiAnnualAction.js';
import { clampSemiAnnualTrust, createProcessSemiAnnualHandler } from '../src/turn/monthlySemiAnnualAction.js';
import type { TurnEvent, TurnGeneral, TurnWorldSnapshot, TurnWorldState } from '../src/turn/types.js';
const buildCity = (id: number, patch: Partial<City> = {}): City => ({
@@ -151,9 +151,8 @@ const environment = {
};
describe('ProcessSemiAnnual monthly action', () => {
it('stores the adjusted trust at the MariaDB FLOAT boundary', () => {
expect(storeLegacySemiAnnualTrust(88.30675 + 10)).toBe(Math.fround(98.30675));
expect(storeLegacySemiAnnualTrust(88.30675 + 10)).not.toBe(98.30675);
it('keeps adjusted trust at full precision', () => {
expect(clampSemiAnnualTrust(88.30675 + 10)).toBe(98.30675);
});
it('preserves the global popIncrease order, neutral double decay, supplied filtering, and nation trait', async () => {
@@ -254,7 +253,7 @@ describe('ProcessSemiAnnual monthly action', () => {
await handler(['gold'], environment, event);
expect(world.getCityById(1)).toMatchObject({ defence: 2_030, wall: 2_030 });
expect(world.getCityById(1)).toMatchObject({ defence: 2_029, wall: 2_029 });
});
it('applies strict legacy resource thresholds to generals and nations for either resource', async () => {