export type GuideValidationSection = "weapon" | "artifact" | "constellations" | "team" | "extra"; interface ValidationIssue { path: readonly PropertyKey[]; message: string; } const fieldMessages: Record = { weaponKey: "กรุณาเลือกอาวุธ", artifactKey: "กรุณาเลือก Artifact", firstArtifactKey: "กรุณาเลือก Artifact ชุดแรก", characterKey: "กรุณาเลือกตัวละคร", overallPercent: "กรุณากรอก Overall % ระหว่าง -9,999 ถึง 9,999", personalPercent: "กรุณากรอก Personal % ระหว่าง -9,999 ถึง 9,999", percent: "กรุณากรอกเปอร์เซ็นต์ระหว่าง -9,999 ถึง 9,999", cumulativePercent: "กรุณากรอก Cumulative % ระหว่าง -9,999 ถึง 9,999", title: "กรุณากรอกชื่อไม่เกิน 160 ตัวอักษร", heading: "กรุณากรอกหัวข้อไม่เกิน 200 ตัวอักษร", combo: "กรุณากรอก Combo", rotationSeconds: "กรุณากรอก Rotation เป็นตัวเลขมากกว่า 0", damage: "กรุณากรอก Damage เป็นตัวเลข 0 ขึ้นไป", }; const sectionLabels: Record = { weapon: "Weapon tier list", artifact: "Artifact", constellations: "Constellations", team: "Team Calc", extra: "Extra sections", }; function indexAfter(path: readonly PropertyKey[], key: string): number | null { const position = path.indexOf(key); const value = path[position + 1]; return position >= 0 && typeof value === "number" ? value : null; } function issueContext(section: GuideValidationSection, path: readonly PropertyKey[], teamNames?: readonly string[]): string { const rowIndex = indexAfter(path, "rows"); const groupIndex = indexAfter(path, "groups"); const teamIndex = indexAfter(path, "teams"); const memberIndex = indexAfter(path, "members"); const sectionIndex = indexAfter(path, "sections"); if (section === "weapon" && groupIndex === null && rowIndex !== null) return `อาวุธอันดับ ${rowIndex + 1}`; if (section === "weapon" && groupIndex !== null) { return rowIndex === null ? `Condition ${groupIndex + 1}` : `Condition ${groupIndex + 1} - อาวุธอันดับ ${rowIndex + 1}`; } if (section === "artifact" && groupIndex !== null) { const group = groupIndex === 0 ? "Late Game" : "Early Game"; return rowIndex === null ? `Artifact ${group}` : `Artifact ${group} อันดับ ${rowIndex + 1}`; } if (section === "constellations" && groupIndex !== null) { return rowIndex === null ? `Condition ${groupIndex + 1}` : `Condition ${groupIndex + 1} - C${rowIndex + 1}`; } if (section === "team" && teamIndex !== null) { const teamName = teamNames?.[teamIndex]?.trim() || `Team ${teamIndex + 1}`; return memberIndex === null ? teamName : `${teamName} - ตัวละคร ${memberIndex + 1}`; } if (section === "extra" && sectionIndex !== null) { return rowIndex === null ? `Extra section ${sectionIndex + 1}` : `Extra section ${sectionIndex + 1} - แถว ${rowIndex + 1}`; } return sectionLabels[section]; } function issueMessage(issue: ValidationIssue): string { const field = issue.path.at(-1); if (typeof field === "string" && fieldMessages[field]) return fieldMessages[field]; if (/[฀-๿]/u.test(issue.message)) return issue.message; if (issue.message.startsWith("Too small")) return "กรุณากรอกข้อมูลให้ครบ"; if (issue.message.startsWith("Too big")) return "ข้อมูลเกินจำนวนหรือความยาวที่กำหนด"; return "กรุณาตรวจสอบข้อมูลให้ถูกต้อง"; } export function formatGuideValidationIssues( section: GuideValidationSection, issues: readonly ValidationIssue[], options: { teamNames?: readonly string[] } = {}, ): string[] { return issues.map((issue) => `${issueContext(section, issue.path, options.teamNames)}: ${issueMessage(issue)}`); }