라운드 접수량 버그 수정 + 토큰→코인 용어 통일 + 외부 배포(NAS)

플레이 피드백 4건(주목도 미차감, 상점 빈 상품, 상점 UX 오해, 재화 명칭)을
검토해 방향이 확정된 항목만 반영하고, 외부 테스터에게 링크를 공유할 수 있게
시놀로지 NAS 배포까지 준비했다.

## 게임 로직

- 라운드 접수량 크리티컬 버그 수정: 합본을 반복하면 라운드가 안 끝나던 문제.
  deskCards에서 파생시키던 값을 순수 누적 카운터(roundIntake)로 교체 — 결정
  노트: 2026-09-18-라운드-접수량-누적카운터
- DeskBar/CoreSwipeCard 정보 역할 분리: "이번 라운드 접수량/한도"는 결재
  화면 전담, DeskBar는 책상에 쌓인 것(총 주목도·축별 분포)만 표시
- 토큰 → 코인 용어 일괄 변경: core/ 전체(식별자·CSS·주석·UI)와 기획서 SSOT
  동기화, lucide Coins 아이콘 추가

## 배포

- vite base를 상대 경로로 변경 (Web Station 서브패스 서빙 시 asset 404 방지)
- 모바일 100vh → 100dvh (주소창 노출 시 하단 버튼 가림 방지)
- 빌드 식별자 표시, 타이틀/테마색/description 정리
- deploy.sh + npm run deploy — SSH 키 권한 문제(777 → StrictModes 거부)와
  NAS rsync 게이트를 scp -O로 우회해 실제 배포까지 검증 완료
  → https://play.mint-grape.duckdns.org/projectss/

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
kyoung5seo
2026-09-18 23:20:22 +09:00
co-authored by Claude Sonnet 5
parent 6398599199
commit 20207ff23c
27 changed files with 451 additions and 239 deletions
+23 -23
View File
@@ -1,7 +1,7 @@
// 의회 엔진 — ProjectSS_코어시스템_기획서.md §7(명분) · §9.2(규약) · §9.3(실적 감사).
// React 의존 없는 순수 함수 + 카탈로그.
//
// 2026-09-15 결정 반영: 토큰 1종 통합(§8.2), 명분 개입 4갈래 재정의(§7.3).
// 2026-09-15 결정 반영: 코인 1종 통합(§8.2), 명분 개입 4갈래 재정의(§7.3).
// 2026-09-17 반영:
// - 유형 D(이득 규약) 카탈로그 신설. 내부 명분("강제 상정")이 불리한 유형 A만 올릴 수 있어
// 실속이 없던 문제를 해결한다 — 이제 이득 규약을 직접 안건에 올릴 수 있다.
@@ -19,9 +19,9 @@ import { HAND_DEFS } from './hands.js';
// 요구치 곡선은 가안: 1라운드 25, 라운드당 +20 (§9.3).
export const requiredScore = (round) => 25 + (round - 1) * 20;
// 실적 점수 = Σ(족보 점수, 라운드 중 합본 누적) + 토큰 납입×5 + 명분 납입×20.
export const settleScore = ({ combineScore, tokensPaid, justificationsPaid }) =>
combineScore + tokensPaid * 5 + justificationsPaid * 20;
// 실적 점수 = Σ(족보 점수, 라운드 중 합본 누적) + 코인 납입×5 + 명분 납입×20.
export const settleScore = ({ combineScore, coinsPaid, justificationsPaid }) =>
combineScore + coinsPaid * 5 + justificationsPaid * 20;
/* ── §9.2 규약 카탈로그 ──
* 유형 A(족보표 변경)·C(징벌)·D(이득)까지 구현. 유형 B(금리형)는 §20.2 콘텐츠 작업 대상. */
@@ -87,22 +87,22 @@ export const PROTOCOL_TYPE_C = [
flavor: '미결 누적에 대한 문책성 규정 — 모든 축의 결재당 게이지 상승이 가산됩니다.',
},
{
id: 'penalty_token_surcharge',
id: 'penalty_coin_surcharge',
name: '긴급 재정 감사 대응',
type: 'C',
effect: { kind: 'token_surcharge', amount: 2 },
flavor: '감사 대응 인력 편성 비용이 모든 토큰 지출에 얹힙니다.',
effect: { kind: 'coin_surcharge', amount: 2 },
flavor: '감사 대응 인력 편성 비용이 모든 코인 지출에 얹힙니다.',
},
];
// 유형 D — 이득 규약. §9.2 "드물게 통과"이므로 후보 등장 확률을 낮게 잡는다(D_CANDIDATE_CHANCE).
// 자산 지급형은 자산 시스템(§10, 3차)이 없어 제외했고, 토큰·족보 완화·한도 완화로 구성했다.
// 자산 지급형은 자산 시스템(§10, 3차)이 없어 제외했고, 코인·족보 완화·한도 완화로 구성했다.
export const PROTOCOL_TYPE_D = [
{
id: 'boon_budget_grant',
name: '예비비 긴급 편성',
type: 'D',
effect: { kind: 'grant_token', amount: 12 },
effect: { kind: 'grant_coin', amount: 12 },
flavor: '이월 예산 일부를 국장 재량으로 집행할 수 있도록 의결되었습니다.',
},
{
@@ -116,7 +116,7 @@ export const PROTOCOL_TYPE_D = [
id: 'boon_admin_simplify',
name: '행정 간소화 지침',
type: 'D',
effect: { kind: 'token_surcharge', amount: -2 },
effect: { kind: 'coin_surcharge', amount: -2 },
flavor: '중복 결재 단계를 축소해 집행 비용을 낮춥니다.',
},
{
@@ -375,20 +375,20 @@ export function protocolEffectDetail(protocol) {
: `결재 1건마다 4대 게이지 상승분이 ${Math.abs(e.amount).toFixed(1)}%p씩 줄어듭니다.`,
tone: e.amount > 0 ? 'bad' : 'good',
};
case 'token_surcharge':
case 'coin_surcharge':
return {
typeLabel,
summary: `토큰 지출 가산 ${e.amount > 0 ? '+' : ''}${e.amount}`,
summary: `코인 지출 가산 ${e.amount > 0 ? '+' : ''}${e.amount}`,
detail: e.amount > 0
? `상점 소각·리롤 등 모든 토큰 지출에 ${e.amount}이(가) 추가로 붙습니다.`
: `모든 토큰 지출 가산이 ${Math.abs(e.amount)} 줄어듭니다 (최소 0).`,
? `상점 소각·리롤 등 모든 코인 지출에 ${e.amount}이(가) 추가로 붙습니다.`
: `모든 코인 지출 가산이 ${Math.abs(e.amount)} 줄어듭니다 (최소 0).`,
tone: e.amount > 0 ? 'bad' : 'good',
};
case 'grant_token':
case 'grant_coin':
return {
typeLabel,
summary: `통과 즉시 토큰 +${e.amount}`,
detail: `표결 통과 시점에 토큰 ${e.amount}을(를) 한 번 지급합니다. 지속 효과는 없습니다.`,
summary: `통과 즉시 코인 +${e.amount}`,
detail: `표결 통과 시점에 코인 ${e.amount}을(를) 한 번 지급합니다. 지속 효과는 없습니다.`,
tone: 'good',
};
case 'attention_cap_bonus':
@@ -418,9 +418,9 @@ export function gaugeSurchargeOf(protocols) {
return protocols.reduce((sum, p) => sum + (p.effect.kind === 'gauge_surcharge' ? p.effect.amount : 0), 0);
}
/** 모든 토큰 지출에 더해지는 가산분 합계 (이득 규약이면 음수). */
export function tokenSurchargeOf(protocols) {
return protocols.reduce((sum, p) => sum + (p.effect.kind === 'token_surcharge' ? p.effect.amount : 0), 0);
/** 모든 코인 지출에 더해지는 가산분 합계 (이득 규약이면 음수). */
export function coinSurchargeOf(protocols) {
return protocols.reduce((sum, p) => sum + (p.effect.kind === 'coin_surcharge' ? p.effect.amount : 0), 0);
}
/** 이번 라운드 주목도 한도에 더해지는 보너스. */
@@ -433,9 +433,9 @@ export function requiredScoreDeltaOf(protocols) {
return protocols.reduce((sum, p) => sum + (p.effect.kind === 'required_score_delta' ? p.effect.amount : 0), 0);
}
/** 통과 즉시 1회 지급되는 토큰. */
export function grantTokenOf(protocol) {
return protocol && protocol.effect.kind === 'grant_token' ? protocol.effect.amount : 0;
/** 통과 즉시 1회 지급되는 코인. */
export function grantCoinOf(protocol) {
return protocol && protocol.effect.kind === 'grant_coin' ? protocol.effect.amount : 0;
}
/* ── 합본 판정에 규약 효과를 얹는다 ── */