feat(battle-sim): implement battle simulation logic and metrics tracking
- Added WarBattleMetrics interface to track attacker and defender skills during battles. - Enhanced WarUnit class with method to log activated skills. - Introduced environment setup for battle simulation, including unit set loading and configuration resolution. - Developed in-memory and Redis transport layers for handling battle simulation requests and results. - Created types and interfaces for battle simulation payloads and responses. - Implemented battle simulation processing logic, including logging and skill tracking. - Added tests for battle simulation processor to ensure functionality and correctness.
This commit is contained in:
@@ -0,0 +1,245 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import type { BattleSimJobPayload } from '../src/battleSim/types.js';
|
||||
import { processBattleSimJob } from '../src/battleSim/processor.js';
|
||||
|
||||
const buildPayload = (action: BattleSimJobPayload['action']): BattleSimJobPayload => ({
|
||||
action,
|
||||
repeatCnt: 1,
|
||||
year: 200,
|
||||
month: 1,
|
||||
seed: 'test-seed',
|
||||
attackerGeneral: {
|
||||
no: 1,
|
||||
name: 'Attacker',
|
||||
nation: 1,
|
||||
turntime: '2026-01-01 00:00:00',
|
||||
personal: null,
|
||||
special2: null,
|
||||
crew: 1000,
|
||||
crewtype: 100,
|
||||
atmos: 100,
|
||||
train: 100,
|
||||
intel: 70,
|
||||
intel_exp: 0,
|
||||
book: null,
|
||||
strength: 70,
|
||||
strength_exp: 0,
|
||||
weapon: null,
|
||||
injury: 0,
|
||||
leadership: 70,
|
||||
leadership_exp: 0,
|
||||
horse: null,
|
||||
item: null,
|
||||
explevel: 0,
|
||||
experience: 100,
|
||||
dedication: 100,
|
||||
officer_level: 3,
|
||||
officer_city: 1,
|
||||
gold: 1000,
|
||||
rice: 1000,
|
||||
dex1: 0,
|
||||
dex2: 0,
|
||||
dex3: 0,
|
||||
dex4: 0,
|
||||
dex5: 0,
|
||||
recent_war: null,
|
||||
warnum: 0,
|
||||
killnum: 0,
|
||||
killcrew: 0,
|
||||
},
|
||||
attackerCity: {
|
||||
city: 1,
|
||||
nation: 1,
|
||||
supply: 1,
|
||||
name: 'AttackerCity',
|
||||
pop: 10000,
|
||||
agri: 1000,
|
||||
comm: 1000,
|
||||
secu: 1000,
|
||||
def: 100,
|
||||
wall: 100,
|
||||
trust: 100,
|
||||
level: 2,
|
||||
pop_max: 10000,
|
||||
agri_max: 1000,
|
||||
comm_max: 1000,
|
||||
secu_max: 1000,
|
||||
def_max: 200,
|
||||
wall_max: 200,
|
||||
dead: 0,
|
||||
state: 0,
|
||||
conflict: '{}',
|
||||
},
|
||||
attackerNation: {
|
||||
type: 'test',
|
||||
tech: 1000,
|
||||
level: 1,
|
||||
capital: 1,
|
||||
nation: 1,
|
||||
name: 'AttackerNation',
|
||||
gold: 1000,
|
||||
rice: 1000,
|
||||
gennum: 1,
|
||||
},
|
||||
defenderGenerals: [
|
||||
{
|
||||
no: 2,
|
||||
name: 'Defender',
|
||||
nation: 2,
|
||||
turntime: '2026-01-01 00:00:00',
|
||||
personal: null,
|
||||
special2: null,
|
||||
crew: 1000,
|
||||
crewtype: 100,
|
||||
atmos: 100,
|
||||
train: 100,
|
||||
intel: 60,
|
||||
intel_exp: 0,
|
||||
book: null,
|
||||
strength: 60,
|
||||
strength_exp: 0,
|
||||
weapon: null,
|
||||
injury: 0,
|
||||
leadership: 60,
|
||||
leadership_exp: 0,
|
||||
horse: null,
|
||||
item: null,
|
||||
explevel: 0,
|
||||
experience: 100,
|
||||
dedication: 100,
|
||||
officer_level: 3,
|
||||
officer_city: 2,
|
||||
gold: 1000,
|
||||
rice: 1000,
|
||||
dex1: 0,
|
||||
dex2: 0,
|
||||
dex3: 0,
|
||||
dex4: 0,
|
||||
dex5: 0,
|
||||
recent_war: null,
|
||||
warnum: 0,
|
||||
killnum: 0,
|
||||
killcrew: 0,
|
||||
},
|
||||
],
|
||||
defenderCity: {
|
||||
city: 2,
|
||||
nation: 2,
|
||||
supply: 1,
|
||||
name: 'DefenderCity',
|
||||
pop: 10000,
|
||||
agri: 1000,
|
||||
comm: 1000,
|
||||
secu: 1000,
|
||||
def: 100,
|
||||
wall: 100,
|
||||
trust: 100,
|
||||
level: 2,
|
||||
pop_max: 10000,
|
||||
agri_max: 1000,
|
||||
comm_max: 1000,
|
||||
secu_max: 1000,
|
||||
def_max: 200,
|
||||
wall_max: 200,
|
||||
dead: 0,
|
||||
state: 0,
|
||||
conflict: '{}',
|
||||
},
|
||||
defenderNation: {
|
||||
type: 'test',
|
||||
tech: 1000,
|
||||
level: 1,
|
||||
capital: 2,
|
||||
nation: 2,
|
||||
name: 'DefenderNation',
|
||||
gold: 1000,
|
||||
rice: 1000,
|
||||
gennum: 1,
|
||||
},
|
||||
unitSet: {
|
||||
id: 'test',
|
||||
name: 'test',
|
||||
crewTypes: [
|
||||
{
|
||||
id: 100,
|
||||
armType: 1,
|
||||
name: '보병',
|
||||
attack: 100,
|
||||
defence: 100,
|
||||
speed: 7,
|
||||
avoid: 10,
|
||||
magicCoef: 0,
|
||||
cost: 9,
|
||||
rice: 9,
|
||||
requirements: [],
|
||||
attackCoef: {},
|
||||
defenceCoef: {},
|
||||
info: [],
|
||||
initSkillTrigger: null,
|
||||
phaseSkillTrigger: null,
|
||||
iActionList: null,
|
||||
},
|
||||
{
|
||||
id: 999,
|
||||
armType: 9,
|
||||
name: '성벽',
|
||||
attack: 0,
|
||||
defence: 0,
|
||||
speed: 1,
|
||||
avoid: 0,
|
||||
magicCoef: 0,
|
||||
cost: 0,
|
||||
rice: 9,
|
||||
requirements: [],
|
||||
attackCoef: {},
|
||||
defenceCoef: {},
|
||||
info: [],
|
||||
initSkillTrigger: null,
|
||||
phaseSkillTrigger: null,
|
||||
iActionList: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
config: {
|
||||
armPerPhase: 500,
|
||||
maxTrainByCommand: 100,
|
||||
maxAtmosByCommand: 100,
|
||||
maxTrainByWar: 110,
|
||||
maxAtmosByWar: 150,
|
||||
castleCrewTypeId: 999,
|
||||
armTypes: {
|
||||
footman: 1,
|
||||
wizard: 4,
|
||||
siege: 5,
|
||||
misc: 6,
|
||||
castle: 9,
|
||||
},
|
||||
},
|
||||
time: {
|
||||
year: 200,
|
||||
month: 1,
|
||||
startYear: 180,
|
||||
},
|
||||
});
|
||||
|
||||
describe('battle sim processor', () => {
|
||||
it('simulates battles and returns summary', () => {
|
||||
const payload = buildPayload('battle');
|
||||
const result = processBattleSimJob(payload);
|
||||
|
||||
expect(result.result).toBe(true);
|
||||
expect(result.reason).toBe('success');
|
||||
expect(result.lastWarLog).toBeTruthy();
|
||||
expect(result.phase).toBeTypeOf('number');
|
||||
expect(result.attackerRice).toBeTypeOf('number');
|
||||
});
|
||||
|
||||
it('returns defender order for reorder action', () => {
|
||||
const payload = buildPayload('reorder');
|
||||
const result = processBattleSimJob(payload);
|
||||
|
||||
expect(result.result).toBe(true);
|
||||
expect(result.order?.length).toBe(1);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user