first commit

This commit is contained in:
a.alinaghipour
2026-04-05 15:53:20 +03:30
commit aa9ed69dd2
96 changed files with 7721 additions and 0 deletions

86
lib/teamValidation.ts Normal file
View File

@@ -0,0 +1,86 @@
export const FORMATIONS: Record<string, { def: number; mid: number; fwd: number }> = {
"4-3-3": { def: 4, mid: 3, fwd: 3 },
"4-4-2": { def: 4, mid: 4, fwd: 2 },
"4-5-1": { def: 4, mid: 5, fwd: 1 },
"3-5-2": { def: 3, mid: 5, fwd: 2 },
"3-4-3": { def: 3, mid: 4, fwd: 3 },
"5-3-2": { def: 5, mid: 3, fwd: 2 },
"5-4-1": { def: 5, mid: 4, fwd: 1 },
};
export type FormationKey = keyof typeof FORMATIONS;
// تعداد مورد نیاز هر پست = ترکیب + 1 ذخیره
export function requiredPerPosition(formation: string) {
const fmt = FORMATIONS[formation] ?? FORMATIONS["4-3-3"];
return {
GK: 2, // 1 اصلی + 1 ذخیره
DEF: fmt.def + 1,
MID: fmt.mid + 1,
FWD: fmt.fwd + 1,
};
}
export type PlayerLike = { position: string; isBench: boolean };
export function validateTeamComposition(
players: PlayerLike[],
formation: string
): { valid: boolean; errors: string[] } {
const fmt = FORMATIONS[formation] ?? FORMATIONS["4-3-3"];
const errors: string[] = [];
const starters = players.filter((p) => !p.isBench);
const bench = players.filter((p) => p.isBench);
// تعداد کل
if (players.length !== 15) {
errors.push(`تیم باید دقیقاً ۱۵ بازیکن داشته باشد (الان: ${players.length})`);
}
// ترکیب اصلی
const startersByPos = countByPos(starters);
if (startersByPos.GK !== 1) errors.push("باید دقیقاً ۱ دروازه‌بان اصلی داشته باشی");
if (startersByPos.DEF !== fmt.def) errors.push(`باید ${fmt.def} مدافع اصلی داشته باشی (الان: ${startersByPos.DEF ?? 0})`);
if (startersByPos.MID !== fmt.mid) errors.push(`باید ${fmt.mid} هافبک اصلی داشته باشی (الان: ${startersByPos.MID ?? 0})`);
if (startersByPos.FWD !== fmt.fwd) errors.push(`باید ${fmt.fwd} مهاجم اصلی داشته باشی (الان: ${startersByPos.FWD ?? 0})`);
// ذخیره‌ها - هر پست باید ۱ ذخیره داشته باشه
const benchByPos = countByPos(bench);
if ((benchByPos.GK ?? 0) < 1) errors.push("باید ۱ دروازه‌بان ذخیره داشته باشی");
if ((benchByPos.DEF ?? 0) < 1) errors.push("باید حداقل ۱ مدافع ذخیره داشته باشی");
if ((benchByPos.MID ?? 0) < 1) errors.push("باید حداقل ۱ هافبک ذخیره داشته باشی");
if ((benchByPos.FWD ?? 0) < 1) errors.push("باید حداقل ۱ مهاجم ذخیره داشته باشی");
return { valid: errors.length === 0, errors };
}
function countByPos(players: PlayerLike[]): Record<string, number> {
return players.reduce((acc, p) => {
acc[p.position] = (acc[p.position] ?? 0) + 1;
return acc;
}, {} as Record<string, number>);
}
// وقتی ترکیب عوض میشه، چک کن آیا بازیکنان فعلی با ترکیب جدید سازگارن
export function getFormationChangeIssues(
players: PlayerLike[],
oldFormation: string,
newFormation: string
): string[] {
const oldFmt = FORMATIONS[oldFormation] ?? FORMATIONS["4-3-3"];
const newFmt = FORMATIONS[newFormation] ?? FORMATIONS["4-3-3"];
const issues: string[] = [];
const starters = players.filter((p) => !p.isBench);
const byPos = countByPos(starters);
if ((byPos.DEF ?? 0) > newFmt.def)
issues.push(`باید ${(byPos.DEF ?? 0) - newFmt.def} مدافع رو به ذخیره ببری یا حذف کنی`);
if ((byPos.MID ?? 0) > newFmt.mid)
issues.push(`باید ${(byPos.MID ?? 0) - newFmt.mid} هافبک رو به ذخیره ببری یا حذف کنی`);
if ((byPos.FWD ?? 0) > newFmt.fwd)
issues.push(`باید ${(byPos.FWD ?? 0) - newFmt.fwd} مهاجم رو به ذخیره ببری یا حذف کنی`);
return issues;
}