feat: NPC 판단 당시 합성 정책을 기록하고 조회한다
This commit is contained in:
@@ -156,6 +156,7 @@ const install = async (
|
||||
{
|
||||
ordinal: input.cursor === undefined ? 0 : 1,
|
||||
steps: [
|
||||
...(input.cursor === undefined ? [{ phase: 'general', generalId: 1, nationId: 2, cityId: 3, npcState: 2, year: 190, month: 6, tick: 100, sequence: 0, kind: 'DECISION_START', reservedAction: '휴식', effectivePolicy: {"schemaVersion":1,"general":{"priority":["징병"],"flags":{"징병":true,"출병":false}},"nation":{"priority":["천도"],"flags":{"천도":true},"values":{"reqNationGold":4321,"reqNationRice":100,"reqHumanWarUrgentGold":100,"reqHumanWarUrgentRice":100,"reqHumanWarRecommandGold":100,"reqHumanWarRecommandRice":100,"reqHumanDevelGold":100,"reqHumanDevelRice":100,"reqNpcWarGold":100,"reqNpcWarRice":100,"reqNpcDevelGold":100,"reqNpcDevelRice":100,"minimumResourceActionAmount":100,"maximumResourceActionAmount":100,"minNpcWarLeadership":100,"minWarCrew":100,"minNpcRecruitCityPopulation":100,"safeRecruitCityPopulationRatio":100,"properWarTrainAtmos":100,"cureThreshold":100},"combatForce":{"1":[2,3]},"supportForce":[4],"developForce":[5]}} }] : []),
|
||||
{
|
||||
phase: 'general',
|
||||
generalId: 1,
|
||||
@@ -165,7 +166,7 @@ const install = async (
|
||||
year: 190,
|
||||
month: 6,
|
||||
tick: 100,
|
||||
sequence: input.cursor === undefined ? 0 : 128,
|
||||
sequence: input.cursor === undefined ? 1 : 128,
|
||||
...(input.cursor === undefined
|
||||
? { kind: 'PROCEDURE_START', procedure: '<b>징병판정</b>' }
|
||||
: {
|
||||
@@ -1156,6 +1157,9 @@ test('NPC decisions are explicit, paginated, independently addressable and escap
|
||||
await page.getByRole('button', { name: '개인 판단 · tick 100', exact: true }).click();
|
||||
await expect(page.getByRole('list', { name: '판단 절차' })).toContainText('<b>징병판정</b>');
|
||||
await expect(page.getByRole('list', { name: '판단 절차' }).locator('b')).toHaveCount(0);
|
||||
await page.getByText('당시 합성 정책', { exact: true }).click();
|
||||
await expect(page.getByRole('list', { name: '판단 절차' })).toContainText('국가 권장 금');
|
||||
await expect(page.getByRole('list', { name: '판단 절차' })).toContainText('4321');
|
||||
await page.getByRole('button', { name: '판단 절차 더 불러오기', exact: true }).click();
|
||||
await expect(page.getByRole('list', { name: '판단 절차' })).toContainText('실행 시도 1');
|
||||
await expect(page.getByRole('list', { name: '판단 절차' })).toContainText(
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<script setup lang="ts">
|
||||
import type { trpc } from '../../utils/trpc';
|
||||
import { fieldLabels } from './policyLabels';
|
||||
type Step = Awaited<ReturnType<typeof trpc.playAudit.decisionDetail.query>>['chunks'][number]['steps'][number];
|
||||
type Policy = NonNullable<Extract<Step, { kind: 'DECISION_START' }>['effectivePolicy']>;
|
||||
defineProps<{ policy: Policy }>();
|
||||
const label = (key: string) => fieldLabels[key.replace('Npc', 'NPC')] ?? key;
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<details>
|
||||
<summary>당시 합성 정책</summary>
|
||||
<p>기본값·서버·국가 설정과 유저 자동턴 옵션이 반영된 정책입니다. 현재 설정으로 재계산하지 않습니다.</p>
|
||||
<section v-for="(part, key) in { general: policy.general, nation: policy.nation }" :key="key">
|
||||
<h4>{{ key === 'general' ? '개인 행동' : '수뇌 행동' }}</h4>
|
||||
<p>우선순위: {{ part.priority.join(' → ') || '없음' }}</p>
|
||||
<ul>
|
||||
<li v-for="(enabled, action) in part.flags" :key="action">
|
||||
{{ action }}: {{ enabled ? '허용' : '제외' }}
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<h4>국가 정책 수치</h4>
|
||||
<dl>
|
||||
<template v-for="(value, key) in policy.nation.values" :key="key">
|
||||
<dt>{{ label(key) }}</dt>
|
||||
<dd>{{ value }}</dd>
|
||||
</template>
|
||||
<dt>전투 부대 편성 (장수: 출발·목적 도시)</dt>
|
||||
<dd>{{ JSON.stringify(policy.nation.combatForce) }}</dd>
|
||||
<dt>지원 부대 장수</dt>
|
||||
<dd>{{ policy.nation.supportForce.join(', ') || '없음' }}</dd>
|
||||
<dt>내정 부대 장수</dt>
|
||||
<dd>{{ policy.nation.developForce.join(', ') || '없음' }}</dd>
|
||||
</dl>
|
||||
<p>실행 직전의 자원 지급 상한·개별 후보 조건과 별도 자동화 권한 판정은 이 정책 표에 포함되지 않습니다.</p>
|
||||
</details>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
details {
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
dd {
|
||||
margin-left: 12px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import AuditEffectivePolicy from './AuditEffectivePolicy.vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { trpc } from '../../utils/trpc';
|
||||
@@ -245,6 +246,10 @@ watch(
|
||||
<template v-for="chunk in detail.chunks" :key="chunk.ordinal"
|
||||
><li v-for="step in chunk.steps" :key="step.sequence" :value="step.sequence + 1">
|
||||
{{ stepText(step) }}
|
||||
<template v-if="step.kind === 'DECISION_START'">
|
||||
<AuditEffectivePolicy v-if="step.effectivePolicy" :policy="step.effectivePolicy" />
|
||||
<p v-else>당시 합성 정책 미수집</p>
|
||||
</template>
|
||||
<ul v-if="step.kind === 'EXECUTION_ATTEMPT'">
|
||||
<li v-for="(check, index) in step.checks" :key="index">
|
||||
{{ checkLabels[check.stage] }} · {{ check.action }} ·
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue';
|
||||
import { fieldLabels } from './policyLabels';
|
||||
import { trpc } from '../../utils/trpc';
|
||||
import AuditRequestState from './AuditRequestState.vue';
|
||||
const props = withDefaults(defineProps<{ id: string; allowPrevious?: boolean }>(), { allowPrevious: true });
|
||||
@@ -11,35 +12,7 @@ const detailLoading = ref(false);
|
||||
let detailGeneration = 0;
|
||||
const select = (id: string | null) => emit('select', id);
|
||||
const message = (cause: unknown) => (cause instanceof Error ? cause.message : '정책 버전을 조회하지 못했습니다.');
|
||||
const fieldLabels: Record<string, string> = {
|
||||
reqNationGold: '국가 권장 금',
|
||||
reqNationRice: '국가 권장 쌀',
|
||||
reqHumanWarUrgentGold: '유저전투장 긴급포상 금',
|
||||
reqHumanWarUrgentRice: '유저전투장 긴급포상 쌀',
|
||||
reqHumanWarRecommandGold: '유저전투장 권장 금',
|
||||
reqHumanWarRecommandRice: '유저전투장 권장 쌀',
|
||||
reqHumanDevelGold: '유저내정장 권장 금',
|
||||
reqHumanDevelRice: '유저내정장 권장 쌀',
|
||||
reqNPCWarGold: 'NPC전투장 권장 금',
|
||||
reqNPCWarRice: 'NPC전투장 권장 쌀',
|
||||
reqNPCDevelGold: 'NPC내정장 권장 금',
|
||||
reqNPCDevelRice: 'NPC내정장 권장 쌀',
|
||||
minimumResourceActionAmount: '포상/몰수/헌납/삼/팜 최소 단위',
|
||||
maximumResourceActionAmount: '포상/몰수/헌납/삼/팜 최대 단위',
|
||||
minWarCrew: '최소 전투 가능 병력 수',
|
||||
minNPCRecruitCityPopulation: 'NPC 최소 징병 가능 인구 수',
|
||||
safeRecruitCityPopulationRatio: '제자리 징병 허용 인구율 (비율)',
|
||||
minNPCWarLeadership: 'NPC 전투 참여 통솔 기준',
|
||||
properWarTrainAtmos: '훈련/사기진작 목표치',
|
||||
cureThreshold: '요양 기준',
|
||||
CombatForce: '전투 부대 편성',
|
||||
SupportForce: '지원 부대 편성',
|
||||
DevelopForce: '내정 부대 편성',
|
||||
priority: '행동 우선순위',
|
||||
war: '전쟁 금지 설정',
|
||||
scout: '임관 권유 설정',
|
||||
secretlimit: '기밀 공개 기준 (년)',
|
||||
};
|
||||
|
||||
const labels = { BASELINE: '최초 관측', CHANGE: '실제 변경', OBSERVED_GAP: '관측 누락 이후 기준' };
|
||||
const loadDetail = async () => {
|
||||
const request = ++detailGeneration;
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
export const fieldLabels: Record<string, string> = {
|
||||
reqNationGold: '국가 권장 금',
|
||||
reqNationRice: '국가 권장 쌀',
|
||||
reqHumanWarUrgentGold: '유저전투장 긴급포상 금',
|
||||
reqHumanWarUrgentRice: '유저전투장 긴급포상 쌀',
|
||||
reqHumanWarRecommandGold: '유저전투장 권장 금',
|
||||
reqHumanWarRecommandRice: '유저전투장 권장 쌀',
|
||||
reqHumanDevelGold: '유저내정장 권장 금',
|
||||
reqHumanDevelRice: '유저내정장 권장 쌀',
|
||||
reqNPCWarGold: 'NPC전투장 권장 금',
|
||||
reqNPCWarRice: 'NPC전투장 권장 쌀',
|
||||
reqNPCDevelGold: 'NPC내정장 권장 금',
|
||||
reqNPCDevelRice: 'NPC내정장 권장 쌀',
|
||||
minimumResourceActionAmount: '포상/몰수/헌납/삼/팜 최소 단위',
|
||||
maximumResourceActionAmount: '포상/몰수/헌납/삼/팜 최대 단위',
|
||||
minWarCrew: '최소 전투 가능 병력 수',
|
||||
minNPCRecruitCityPopulation: 'NPC 최소 징병 가능 인구 수',
|
||||
safeRecruitCityPopulationRatio: '제자리 징병 허용 인구율 (비율)',
|
||||
minNPCWarLeadership: 'NPC 전투 참여 통솔 기준',
|
||||
properWarTrainAtmos: '훈련/사기진작 목표치',
|
||||
cureThreshold: '요양 기준',
|
||||
CombatForce: '전투 부대 편성',
|
||||
SupportForce: '지원 부대 편성',
|
||||
DevelopForce: '내정 부대 편성',
|
||||
priority: '행동 우선순위',
|
||||
war: '전쟁 금지 설정',
|
||||
scout: '임관 권유 설정',
|
||||
secretlimit: '기밀 공개 기준 (년)',
|
||||
};
|
||||
Reference in New Issue
Block a user