걸음 카드 보상 칸 · Music Shake 이어하기 재생

This commit is contained in:
Sn-Kinos
2026-10-06 04:15:28 +09:00
parent 99b9bb8665
commit 976e569a56
9 changed files with 94 additions and 13 deletions
+17 -1
View File
@@ -132,9 +132,25 @@ enum QuestType {
/// 출석은 `fn-quest-attend` 가 `config/policy.attendPop` 을 지급하고
/// `quests.rewardPop` 을 보지 않는다. 그래서 출석만 운영값을 읽는다. 운영값이
/// 없으면 null — 숫자를 지어내지 않고 화면이 중립 문구를 쓴다.
int? rewardFrom(Map<String, dynamic> quest, Map<String, dynamic> policy) {
///
/// 운영 걸음 Quest 는 `fn-quest-steps` 가 `config/policy.stepTiers` 구간표(원장 B-26 —
/// 1 천/5 천/1 만/1.5 만보 = 5/6/7/8)대로 지급하고 `quests.rewardPop` 을 보지 않는다. 카드의
/// 목표 칸이 오늘 다음 구간(`[cleared]` 번째)이므로 보상 칸도 **그 구간의 지급액**이다.
int? rewardFrom(
Map<String, dynamic> quest,
Map<String, dynamic> policy, {
int cleared = 0,
}) {
// 시청 · 스트리밍은 무보상 참여다(C-04) — 문서 값과 무관하게 0.
if (this == QuestType.streaming) return 0;
if (this == QuestType.steps && quest['authorUid'] is! String) {
final tiers = [
for (final row in policy['stepTiers'] is List ? policy['stepTiers'] as List : const [])
if (row is Map && row['steps'] is num && row['pop'] is num)
(steps: row['steps'] as num, pop: (row['pop'] as num).round()),
]..sort((a, b) => a.steps.compareTo(b.steps));
if (tiers.isNotEmpty) return tiers[cleared.clamp(0, tiers.length - 1)].pop;
}
// Music Shake 는 BPM 판정 성공 시 일반 POP(원장 B-24 · 보상액 운영값). 서버
// (`fn-quest-verify-music-shake`)가 퀘스트의 `rewardPop` 을, 없으면
// `config/policy.musicShake.pop` 을 기본액으로 쓴다. 운영값이 둘 다 없을 때만 중립 문구.