import { ESCALATION_THRESHOLDS } from "@/lib/config";
import type { EscalationLevel } from "@/lib/types";
/**
* エスカレーション(L1〜L3)の判定
*
* ★「連続」はカレンダー日ではなく「スケジュール存在日の連続」で数える(D-026)★
*
* 例)月水金スケジュールの施設で 月・水・金 と3回連続で失敗した場合、
* カレンダー上は5日間だが、スケジュール存在日の連続は3日なので L3。
* 火・木は清掃予定がないため、連続を途切れさせない。
*
* この関数は「スケジュール存在日だけに絞り込んだ結果」を受け取る前提です。
* どの日がスケジュール存在日かの判断(曜日計算、active フラグ、日跨ぎ等)は
* データ取得側の責任とし、判定ロジックには持ち込みません。
*/
/** スケジュール存在日1日分の結果 */
export interface ScheduleDayResult {
/** YYYY-MM-DD */
date: string;
/** その日が「問題あり」だったか(△以下 or 出発失敗) */
isProblem: boolean;
}
/**
* 直近から遡って、問題が何日続いているかを数える。
*
* @param days スケジュール存在日のみの結果。日付昇順(古い→新しい)で渡すこと
* @returns 直近の連続問題日数。最新日が問題なしなら 0
*/
export function countConsecutiveProblemDays(days: ScheduleDayResult[]): number {
let count = 0;
for (let i = days.length - 1; i >= 0; i -= 1) {
if (!days[i].isProblem) break;
count += 1;
}
return count;
}
/**
* 連続日数からエスカレーションレベルを決める。
*
* | レベル | 条件 |
* |---|---|
* | L1 | 初回の問題(1日) |
* | L2 | 2日連続 |
* | L3 | 3日以上連続 |
*
* @returns 問題がない(0日)場合は null
*/
export function judgeEscalationLevel(
consecutiveDays: number
): EscalationLevel | null {
if (consecutiveDays <= 0) return null;
if (consecutiveDays >= ESCALATION_THRESHOLDS.level3Days) return "L3";
if (consecutiveDays >= ESCALATION_THRESHOLDS.level2Days) return "L2";
return "L1";
}
/** 結果配列から直接レベルを求めるショートカット */
export function judgeEscalation(days: ScheduleDayResult[]): {
consecutiveDays: number;
level: EscalationLevel | null;
} {
const consecutiveDays = countConsecutiveProblemDays(days);
return { consecutiveDays, level: judgeEscalationLevel(consecutiveDays) };
}