Files
football-next/prisma/seed.ts
a.alinaghipour aa9ed69dd2 first commit
2026-04-05 15:53:20 +03:30

236 lines
16 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { PrismaClient } from "@prisma/client";
import bcrypt from "bcryptjs";
// DEFAULT_RULES رو مستقیم اینجا تعریف می‌کنیم تا از @/ alias استفاده نکنیم
const DEFAULT_RULES = {
GK: { GOAL: 10, ASSIST: 3, YELLOW_CARD: -1, RED_CARD: -3, SECOND_YELLOW: -3, CLEAN_SHEET: 6, PENALTY_SAVED: 5, PENALTY_MISSED: -2, OWN_GOAL: -2, MOTM: 3, EXTRA_TIME_BONUS: 1, INJURY_NO_SUB: -1 },
DEF: { GOAL: 8, ASSIST: 3, YELLOW_CARD: -1, RED_CARD: -3, SECOND_YELLOW: -3, CLEAN_SHEET: 4, PENALTY_SAVED: 0, PENALTY_MISSED: -2, OWN_GOAL: -2, MOTM: 3, EXTRA_TIME_BONUS: 1, INJURY_NO_SUB: -1 },
MID: { GOAL: 5, ASSIST: 3, YELLOW_CARD: -2, RED_CARD: -3, SECOND_YELLOW: -3, CLEAN_SHEET: 1, PENALTY_SAVED: 0, PENALTY_MISSED: -2, OWN_GOAL: -2, MOTM: 3, EXTRA_TIME_BONUS: 1, INJURY_NO_SUB: -1 },
FWD: { GOAL: 4, ASSIST: 3, YELLOW_CARD: -1, RED_CARD: -3, SECOND_YELLOW: -3, CLEAN_SHEET: 0, PENALTY_SAVED: 0, PENALTY_MISSED: -2, OWN_GOAL: -2, MOTM: 3, EXTRA_TIME_BONUS: 1, INJURY_NO_SUB: -1 },
} as const;
const prisma = new PrismaClient();
// ترکیب پیش‌فرض تیم‌های ملی معروف (بر اساس آخرین اطلاعات)
const COUNTRY_FORMATIONS: Record<string, string> = {
BRA: "4-3-3", FRA: "4-3-3", ARG: "4-3-3", ENG: "4-3-3",
ESP: "4-3-3", GER: "4-2-3-1", POR: "4-3-3", NED: "4-3-3",
BEL: "4-3-3", CRO: "4-3-3", MAR: "4-3-3", IRN: "4-5-1",
URU: "4-3-3", SEN: "4-3-3", KOR: "4-3-3", JPN: "4-3-3",
MEX: "4-3-3", USA: "4-3-3", CAN: "4-3-3", AUS: "4-3-3",
POL: "4-3-3", DEN: "4-3-3", SUI: "4-2-3-1", SRB: "3-4-3",
WAL: "5-3-2", TUN: "4-3-3", CMR: "4-3-3", GHA: "4-2-3-1",
ECU: "4-3-3", QAT: "5-3-2", KSA: "4-3-3", CRC: "5-4-1",
};
const COUNTRIES = [
{ name: "برزیل", code: "BRA", flag: "🇧🇷", group: "G" },
{ name: "سربیا", code: "SRB", flag: "🇷🇸", group: "G" },
{ name: "سوئیس", code: "SUI", flag: "🇨🇭", group: "G" },
{ name: "کامرون", code: "CMR", flag: "🇨🇲", group: "G" },
{ name: "فرانسه", code: "FRA", flag: "🇫🇷", group: "D" },
{ name: "استرالیا", code: "AUS", flag: "🇦🇺", group: "D" },
{ name: "دانمارک", code: "DEN", flag: "🇩🇰", group: "D" },
{ name: "تونس", code: "TUN", flag: "🇹🇳", group: "D" },
{ name: "آرژانتین", code: "ARG", flag: "🇦🇷", group: "C" },
{ name: "عربستان", code: "KSA", flag: "🇸🇦", group: "C" },
{ name: "مکزیک", code: "MEX", flag: "🇲🇽", group: "C" },
{ name: "لهستان", code: "POL", flag: "🇵🇱", group: "C" },
{ name: "ایران", code: "IRN", flag: "🇮🇷", group: "B" },
{ name: "انگلیس", code: "ENG", flag: "🏴󠁧󠁢󠁥󠁮󠁧󠁿", group: "B" },
{ name: "آمریکا", code: "USA", flag: "🇺🇸", group: "B" },
{ name: "ولز", code: "WAL", flag: "🏴󠁧󠁢󠁷󠁬󠁳󠁿", group: "B" },
{ name: "آلمان", code: "GER", flag: "🇩🇪", group: "E" },
{ name: "ژاپن", code: "JPN", flag: "🇯🇵", group: "E" },
{ name: "اسپانیا", code: "ESP", flag: "🇪🇸", group: "E" },
{ name: "کاستاریکا", code: "CRC", flag: "🇨🇷", group: "E" },
{ name: "بلژیک", code: "BEL", flag: "🇧🇪", group: "F" },
{ name: "کانادا", code: "CAN", flag: "🇨🇦", group: "F" },
{ name: "مراکش", code: "MAR", flag: "🇲🇦", group: "F" },
{ name: "کرواسی", code: "CRO", flag: "🇭🇷", group: "F" },
{ name: "پرتغال", code: "POR", flag: "🇵🇹", group: "H" },
{ name: "غنا", code: "GHA", flag: "🇬🇭", group: "H" },
{ name: "اروگوئه", code: "URU", flag: "🇺🇾", group: "H" },
{ name: "کره جنوبی", code: "KOR", flag: "🇰🇷", group: "H" },
{ name: "هلند", code: "NED", flag: "🇳🇱", group: "A" },
{ name: "سنگال", code: "SEN", flag: "🇸🇳", group: "A" },
{ name: "اکوادور", code: "ECU", flag: "🇪🇨", group: "A" },
{ name: "قطر", code: "QAT", flag: "🇶🇦", group: "A" },
];
const PLAYERS_DATA = [
{ name: "آلیسون بکر", pos: "GK", code: "BRA", price: 6.0, pts: 42 },
{ name: "تیاگو سیلوا", pos: "DEF", code: "BRA", price: 6.5, pts: 38 },
{ name: "مارکینیوس", pos: "DEF", code: "BRA", price: 6.0, pts: 35 },
{ name: "کاسمیرو", pos: "MID", code: "BRA", price: 8.0, pts: 52 },
{ name: "نیمار", pos: "FWD", code: "BRA", price: 11.5, pts: 68 },
{ name: "وینیسیوس جونیور", pos: "FWD", code: "BRA", price: 10.5, pts: 72 },
{ name: "ریچارلیسون", pos: "FWD", code: "BRA", price: 8.5, pts: 55 },
{ name: "هوگو لوریس", pos: "GK", code: "FRA", price: 6.0, pts: 40 },
{ name: "رافائل واران", pos: "DEF", code: "FRA", price: 6.5, pts: 36 },
{ name: "کیلیان امباپه", pos: "FWD", code: "FRA", price: 12.5, pts: 88 },
{ name: "آنتوان گریزمان", pos: "MID", code: "FRA", price: 9.5, pts: 62 },
{ name: "اولیویه ژیرو", pos: "FWD", code: "FRA", price: 7.5, pts: 48 },
{ name: "اوسمان دمبله", pos: "FWD", code: "FRA", price: 8.0, pts: 44 },
{ name: "امیلیانو مارتینز", pos: "GK", code: "ARG", price: 6.5, pts: 55 },
{ name: "لیونل مسی", pos: "FWD", code: "ARG", price: 12.5, pts: 92 },
{ name: "خولیان آلوارز", pos: "FWD", code: "ARG", price: 8.5, pts: 60 },
{ name: "رودریگو دپاول", pos: "MID", code: "ARG", price: 7.5, pts: 45 },
{ name: "نیکولاس اوتامندی", pos: "DEF", code: "ARG", price: 5.5, pts: 32 },
{ name: "جوردن پیکفورد", pos: "GK", code: "ENG", price: 5.5, pts: 38 },
{ name: "جود بلینگهام", pos: "MID", code: "ENG", price: 10.5, pts: 75 },
{ name: "هری کین", pos: "FWD", code: "ENG", price: 11.0, pts: 70 },
{ name: "بوکایو ساکا", pos: "MID", code: "ENG", price: 8.5, pts: 58 },
{ name: "فیل فودن", pos: "MID", code: "ENG", price: 9.0, pts: 62 },
{ name: "جان استونز", pos: "DEF", code: "ENG", price: 6.0, pts: 34 },
{ name: "اونای سیمون", pos: "GK", code: "ESP", price: 5.5, pts: 36 },
{ name: "پدری", pos: "MID", code: "ESP", price: 9.0, pts: 60 },
{ name: "گاوی", pos: "MID", code: "ESP", price: 8.5, pts: 55 },
{ name: "آلوارو موراتا", pos: "FWD", code: "ESP", price: 7.5, pts: 46 },
{ name: "دنی اولمو", pos: "MID", code: "ESP", price: 7.0, pts: 42 },
{ name: "مانوئل نویر", pos: "GK", code: "GER", price: 6.0, pts: 38 },
{ name: "توماس مولر", pos: "MID", code: "GER", price: 8.0, pts: 50 },
{ name: "کای هاورتز", pos: "MID", code: "GER", price: 8.5, pts: 52 },
{ name: "یامله موسیالا", pos: "MID", code: "GER", price: 9.0, pts: 65 },
{ name: "آنتونیو رودیگر", pos: "DEF", code: "GER", price: 5.5, pts: 30 },
{ name: "دیوگو کوستا", pos: "GK", code: "POR", price: 5.5, pts: 35 },
{ name: "کریستیانو رونالدو", pos: "FWD", code: "POR", price: 11.0, pts: 65 },
{ name: "برونو فرناندز", pos: "MID", code: "POR", price: 10.0, pts: 70 },
{ name: "رافائل لئائو", pos: "FWD", code: "POR", price: 8.5, pts: 55 },
{ name: "روبن دیاز", pos: "DEF", code: "POR", price: 6.0, pts: 36 },
{ name: "علیرضا بیرانوند", pos: "GK", code: "IRN", price: 5.0, pts: 28 },
{ name: "مهدی طارمی", pos: "FWD", code: "IRN", price: 8.0, pts: 50 },
{ name: "سردار آزمون", pos: "FWD", code: "IRN", price: 7.5, pts: 44 },
{ name: "علی کریمی", pos: "MID", code: "IRN", price: 6.0, pts: 32 },
{ name: "رامین رضاییان", pos: "DEF", code: "IRN", price: 5.0, pts: 22 },
{ name: "یاسین بونو", pos: "GK", code: "MAR", price: 6.5, pts: 58 },
{ name: "اشرف حکیمی", pos: "DEF", code: "MAR", price: 8.0, pts: 62 },
{ name: "حکیم زیاش", pos: "MID", code: "MAR", price: 7.5, pts: 48 },
{ name: "یوسف النصیری", pos: "FWD", code: "MAR", price: 7.0, pts: 45 },
{ name: "دومینیک لیواکوویچ", pos: "GK", code: "CRO", price: 6.0, pts: 50 },
{ name: "لوکا مودریچ", pos: "MID", code: "CRO", price: 9.5, pts: 68 },
{ name: "ایوان پریشیچ", pos: "MID", code: "CRO", price: 7.5, pts: 48 },
{ name: "آندره کراماریچ", pos: "FWD", code: "CRO", price: 7.0, pts: 44 },
{ name: "آندریس نوپرت", pos: "GK", code: "NED", price: 5.5, pts: 36 },
{ name: "ویرخیل فان دایک", pos: "DEF", code: "NED", price: 7.0, pts: 48 },
{ name: "دنزل دامفریس", pos: "DEF", code: "NED", price: 7.5, pts: 52 },
{ name: "کودی گاکپو", pos: "FWD", code: "NED", price: 8.0, pts: 58 },
{ name: "تیبو کورتوا", pos: "GK", code: "BEL", price: 6.5, pts: 44 },
{ name: "کوین دبروینه", pos: "MID", code: "BEL", price: 11.0, pts: 72 },
{ name: "رومله لوکاکو", pos: "FWD", code: "BEL", price: 9.5, pts: 55 },
];
async function main() {
console.log("🌱 Seeding...");
// ─── ادمین و کاربران ─────────────────────────────────
const adminPwd = await bcrypt.hash("admin123", 10);
await prisma.user.upsert({ where: { email: "admin@worldcup.com" }, update: {},
create: { email: "admin@worldcup.com", name: "ادمین", password: adminPwd, role: "ADMIN" } });
const userPwd = await bcrypt.hash("user123", 10);
const users = [];
for (const u of [{ email: "ali@test.com", name: "علی احمدی" }, { email: "sara@test.com", name: "سارا رضایی" }, { email: "reza@test.com", name: "رضا محمدی" }]) {
const user = await prisma.user.upsert({ where: { email: u.email }, update: {}, create: { ...u, password: userPwd } });
users.push(user);
}
// ─── گروه‌ها ──────────────────────────────────────────
const groupMap: Record<string, string> = {};
for (const name of ["A","B","C","D","E","F","G","H"]) {
const g = await prisma.group.upsert({ where: { name }, update: {}, create: { name } });
groupMap[name] = g.id;
}
// ─── تیم‌های ملی ─────────────────────────────────────
const countryMap: Record<string, string> = {};
for (const c of COUNTRIES) {
const country = await prisma.country.upsert({ where: { code: c.code }, update: { flagUrl: c.flag, defaultFormation: COUNTRY_FORMATIONS[c.code] ?? "4-3-3" },
create: { name: c.name, code: c.code, flagUrl: c.flag, groupId: groupMap[c.group], defaultFormation: COUNTRY_FORMATIONS[c.code] ?? "4-3-3" } });
countryMap[c.code] = country.id;
}
// ─── بازیکنان ─────────────────────────────────────────
for (const p of PLAYERS_DATA) {
const countryId = countryMap[p.code];
if (!countryId) continue;
await prisma.player.create({ data: { name: p.name, position: p.pos as any, countryId, price: p.price, totalPoints: p.pts } });
}
// ─── قوانین امتیازدهی پیش‌فرض ────────────────────────
const positions = ["GK", "DEF", "MID", "FWD"] as const;
for (const pos of positions) {
const rules = DEFAULT_RULES[pos];
for (const [eventType, points] of Object.entries(rules)) {
await prisma.scoringRule.upsert({
where: { position_eventType: { position: pos, eventType: eventType as any } },
update: { points: points as number },
create: { position: pos, eventType: eventType as any, points: points as number },
});
}
}
// ─── دورها ────────────────────────────────────────────
const round1 = await prisma.round.upsert({ where: { number: 1 }, update: {},
create: { number: 1, name: "دور اول - مرحله گروهی", isActive: true, deadline: new Date("2026-06-15T10:00:00Z") } });
const round2 = await prisma.round.upsert({ where: { number: 2 }, update: {},
create: { number: 2, name: "دور دوم - مرحله گروهی", deadline: new Date("2026-06-22T10:00:00Z") } });
const round3 = await prisma.round.upsert({ where: { number: 3 }, update: {},
create: { number: 3, name: "دور سوم - مرحله گروهی", deadline: new Date("2026-06-29T10:00:00Z") } });
const round4 = await prisma.round.upsert({ where: { number: 4 }, update: {},
create: { number: 4, name: "دور چهارم - یک‌هشتم نهایی", deadline: new Date("2026-07-05T10:00:00Z") } });
// ─── بازی‌ها ──────────────────────────────────────────
const matchesData = [
// دور اول - بازی اول هر تیم
{ home: "QAT", away: "ECU", hS: 0, aS: 2, st: "FINISHED", date: "2026-06-20T16:00:00Z", rId: round1.id },
{ home: "ENG", away: "IRN", hS: 6, aS: 2, st: "FINISHED", date: "2026-06-21T13:00:00Z", rId: round1.id },
{ home: "ARG", away: "KSA", hS: 1, aS: 2, st: "FINISHED", date: "2026-06-22T10:00:00Z", rId: round1.id },
{ home: "FRA", away: "AUS", hS: 4, aS: 1, st: "FINISHED", date: "2026-06-22T19:00:00Z", rId: round1.id },
{ home: "GER", away: "JPN", hS: 1, aS: 2, st: "FINISHED", date: "2026-06-23T13:00:00Z", rId: round1.id },
{ home: "ESP", away: "CRC", hS: 7, aS: 0, st: "FINISHED", date: "2026-06-23T19:00:00Z", rId: round1.id },
{ home: "BEL", away: "CAN", hS: 1, aS: 0, st: "FINISHED", date: "2026-06-23T16:00:00Z", rId: round1.id },
{ home: "BRA", away: "SRB", hS: 2, aS: 0, st: "FINISHED", date: "2026-06-24T19:00:00Z", rId: round1.id },
{ home: "POR", away: "GHA", hS: 3, aS: 2, st: "FINISHED", date: "2026-06-24T16:00:00Z", rId: round1.id },
{ home: "MAR", away: "CRO", hS: 0, aS: 0, st: "FINISHED", date: "2026-06-23T10:00:00Z", rId: round1.id },
{ home: "NED", away: "SEN", hS: 2, aS: 0, st: "FINISHED", date: "2026-06-21T16:00:00Z", rId: round1.id },
// دور دوم - بازی دوم هر تیم
{ home: "IRN", away: "WAL", hS: 2, aS: 0, st: "FINISHED", date: "2026-06-25T13:00:00Z", rId: round2.id },
{ home: "FRA", away: "DEN", hS: 2, aS: 1, st: "FINISHED", date: "2026-06-26T19:00:00Z", rId: round2.id },
{ home: "ARG", away: "MEX", hS: 2, aS: 0, st: "FINISHED", date: "2026-06-26T22:00:00Z", rId: round2.id },
{ home: "BRA", away: "SUI", hS: 1, aS: 0, st: "FINISHED", date: "2026-06-28T19:00:00Z", rId: round2.id },
{ home: "ENG", away: "USA", hS: 0, aS: 0, st: "FINISHED", date: "2026-06-25T19:00:00Z", rId: round2.id },
// دور سوم - بازی سوم گروهی
{ home: "BRA", away: "CMR", hS: 1, aS: 0, st: "SCHEDULED", date: "2026-07-02T19:00:00Z", rId: round3.id },
{ home: "FRA", away: "TUN", hS: null, aS: null, st: "SCHEDULED", date: "2026-07-01T16:00:00Z", rId: round3.id },
// دور چهارم - یک‌هشتم
{ home: "NED", away: "ARG", hS: 2, aS: 2, st: "FINISHED", date: "2026-12-09T19:00:00Z", rId: round4.id, stage: "ROUND_OF_16" },
{ home: "FRA", away: "ENG", hS: 2, aS: 1, st: "FINISHED", date: "2026-12-10T19:00:00Z", rId: round4.id, stage: "ROUND_OF_16" },
{ home: "ARG", away: "FRA", hS: 3, aS: 3, st: "FINISHED", date: "2026-12-18T15:00:00Z", rId: round4.id, stage: "FINAL" },
];
for (const m of matchesData) {
const homeId = countryMap[m.home], awayId = countryMap[m.away];
if (!homeId || !awayId) continue;
await prisma.match.create({ data: {
homeTeamId: homeId, awayTeamId: awayId,
homeScore: m.hS ?? null, awayScore: m.aS ?? null,
status: m.st as any, stage: (m.stage ?? "GROUP") as any,
matchDate: new Date(m.date), roundId: m.rId,
}});
}
// ─── پکیج‌ها ──────────────────────────────────────────
for (const pkg of [
{ id: "pkg-silver", name: "پکیج نقره‌ای", budgetBonus: 10, price: 50000, description: "۱۰ میلیون به بودجه اضافه کن" },
{ id: "pkg-gold", name: "پکیج طلایی", budgetBonus: 20, price: 90000, description: "۲۰ میلیون به بودجه اضافه کن" },
{ id: "pkg-diamond", name: "پکیج الماس", budgetBonus: 30, price: 120000, description: "۳۰ میلیون به بودجه اضافه کن" },
]) {
await prisma.package.upsert({ where: { id: pkg.id }, update: {}, create: pkg });
}
console.log("✅ Seed done! admin@worldcup.com / admin123 | ali@test.com / user123");
}
main().catch(console.error).finally(() => prisma.$disconnect());