Files
flxn-app/test.js
2025-10-16 09:12:11 -05:00

269 lines
9.3 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 PocketBase from "pocketbase";
import * as xlsx from "xlsx";
import { nanoid } from "nanoid";
import { createTeamsService } from "./src/lib/pocketbase/services/teams.ts";
import { createPlayersService } from "./src/lib/pocketbase/services/players.ts";
import { createMatchesService } from "./src/lib/pocketbase/services/matches.ts";
import { createTournamentsService } from "./src/lib/pocketbase/services/tournaments.ts";
const POCKETBASE_URL = "http://127.0.0.1:8090";
const EXCEL_FILE_PATH = "./Teams-2.xlsx";
const ADMIN_EMAIL = "kyle.yohler@gmail.com";
const ADMIN_PASSWORD = "xj44aqz9CWrNNM0o";
// --- Helpers ---
async function createPlayerIfMissing(playersService, nameColumn, idColumn) {
const playerId = idColumn?.trim();
if (playerId) return playerId;
let firstName, lastName;
if (!nameColumn || !nameColumn.trim()) {
firstName = `Player_${nanoid(4)}`;
lastName = "(Regional)";
} else {
const parts = nameColumn.trim().split(" ");
firstName = parts[0];
lastName = parts[1] || "(Regional)";
}
const newPlayer = await playersService.createPlayer({ first_name: firstName, last_name: lastName });
return newPlayer.id;
}
async function handleTeamsSheet(rows, teamsService, playersService, pb, tournamentIdMap = {}) {
console.log(`📥 Importing ${rows.length} teams...`);
const teamIdMap = {}; // spreadsheet ID -> PocketBase ID
for (const [i, row] of rows.entries()) {
try {
const spreadsheetTeamId = row["ID"]?.toString().trim();
if (!spreadsheetTeamId) {
console.warn(`⚠️ [${i + 1}] Team row missing spreadsheet ID, skipping.`);
continue;
}
const p1Id = await createPlayerIfMissing(playersService, row["P1 Name"], row["P1 ID"]);
const p2Id = await createPlayerIfMissing(playersService, row["P2 Name"], row["P2 ID"]);
let name = row["Name"]?.trim();
if (!name) {
const p1First = row["P1 Name"]?.split(" ")[0] || "Player1";
const p2First = row["P2 Name"]?.split(" ")[0] || "Player2";
name = `${p1First} and ${p2First}`;
console.warn(`⚠️ [${i + 1}] No team name found. Using generated name: ${name}`);
}
const existing = await pb.collection("teams").getFullList({
filter: `name = "${name}"`,
fields: "id",
});
if (existing.length > 0) {
console.log(` [${i + 1}] Team "${name}" already exists, skipping.`);
teamIdMap[spreadsheetTeamId] = existing[0].id;
continue;
}
// If there's a tournament for this team, get its PB ID
const tournamentSpreadsheetId = row["Tournament ID"]?.toString().trim();
const tournamentId = tournamentSpreadsheetId ? tournamentIdMap[tournamentSpreadsheetId] : undefined;
const teamInput = {
name,
primary_color: row.primary_color || "",
accent_color: row.accent_color || "",
logo: row.logo || "",
players: [p1Id, p2Id],
tournament: tournamentId, // single tournament relation,
private: true
};
const team = await teamsService.createTeam(teamInput);
teamIdMap[spreadsheetTeamId] = team.id;
console.log(`✅ [${i + 1}] Created team: ${team.name} with players: ${[p1Id, p2Id].join(", ")}`);
// Add the team to the tournament's "teams" relation
if (tournamentId) {
await pb.collection("tournaments").update(tournamentId, {
"teams+": [team.id],
});
console.log(`✅ Added team "${team.name}" to tournament ${tournamentId}`);
}
} catch (err) {
console.error(`❌ [${i + 1}] Failed to create team: ${err.message}`);
}
}
return teamIdMap;
}
async function handleTournamentSheet(rows, tournamentsService, teamIdMap, pb) {
console.log(`📥 Importing ${rows.length} tournaments...`);
const tournamentIdMap = {};
const validFormats = ["double_elim", "single_elim", "groups", "swiss", "swiss_bracket"];
for (const [i, row] of rows.entries()) {
try {
const spreadsheetId = row["ID"]?.toString().trim();
if (!spreadsheetId) {
console.warn(`⚠️ [${i + 1}] Tournament missing spreadsheet ID, skipping.`);
continue;
}
if (!row["Name"]) {
console.warn(`⚠️ [${i + 1}] Tournament name missing, skipping.`);
continue;
}
const format = validFormats.includes(row["Format"]) ? row["Format"] : "double_elim";
// Convert start_time to ISO datetime string
let startTime = null;
if (row["Start Time"]) {
try {
startTime = new Date(row["Start Time"]).toISOString();
} catch (e) {
console.warn(`⚠️ [${i + 1}] Invalid start time format, using null`);
}
}
const tournamentInput = {
name: row["Name"],
start_time: startTime,
format,
regional: true,
teams: Object.values(teamIdMap), // Add all created teams
};
const tournament = await tournamentsService.createTournament(tournamentInput);
tournamentIdMap[spreadsheetId] = tournament.id;
console.log(`✅ [${i + 1}] Created tournament: ${tournament.name} with ${Object.values(teamIdMap).length} teams`);
} catch (err) {
console.error(`❌ [${i + 1}] Failed to create tournament: ${err.message}`);
}
}
return tournamentIdMap;
}
async function handleMatchesSheet(rows, matchesService, teamIdMap, tournamentIdMap, pb) {
console.log(`📥 Importing ${rows.length} matches...`);
const tournamentMatchesMap = {};
for (const [i, row] of rows.entries()) {
try {
const homeId = teamIdMap[row["Home ID"]];
const awayId = teamIdMap[row["Away ID"]];
const tournamentId = tournamentIdMap[row["Tournament ID"]];
if (!homeId || !awayId || !tournamentId) {
console.warn(`⚠️ [${i + 1}] Could not find mapping for Home, Away, or Tournament, skipping.`);
continue;
}
// --- Ensure the teams are linked to the tournament ---
for (const teamId of [homeId, awayId]) {
const team = await pb.collection("teams").getOne(teamId, { fields: "tournaments" });
const tournaments = team.tournaments || [];
if (!tournaments.includes(tournamentId)) {
// Add tournament to team
await pb.collection("teams").update(teamId, { "tournaments+": [tournamentId] });
// Add team to tournament
await pb.collection("tournaments").update(tournamentId, { "teams+": [teamId] });
console.log(`✅ Linked team ${team.name} to tournament ${tournamentId}`);
}
}
// --- Create match ---
const data = {
tournament: tournamentId,
home: homeId,
away: awayId,
home_cups: Number(row["Home cups"] || 0),
away_cups: Number(row["Away cups"] || 0),
status: "ended",
lid: i+1
};
const match = await matchesService.createMatch(data);
console.log(`✅ [${i + 1}] Created match ID: ${match.id}`);
if (!tournamentMatchesMap[tournamentId]) tournamentMatchesMap[tournamentId] = [];
tournamentMatchesMap[tournamentId].push(match.id);
} catch (err) {
console.error(`❌ [${i + 1}] Failed to create match: ${err.message}`);
}
}
// Update each tournament with the created match IDs
for (const [tournamentId, matchIds] of Object.entries(tournamentMatchesMap)) {
try {
await pb.collection("tournaments").update(tournamentId, { "matches+": matchIds });
console.log(`✅ Updated tournament ${tournamentId} with ${matchIds.length} matches`);
} catch (err) {
console.error(`❌ Failed to update tournament ${tournamentId} with matches: ${err.message}`);
}
}
}
// --- Main Import ---
export async function importExcel() {
const pb = new PocketBase(POCKETBASE_URL);
await pb.admins.authWithPassword(ADMIN_EMAIL, ADMIN_PASSWORD);
const teamsService = createTeamsService(pb);
const playersService = createPlayersService(pb);
const tournamentsService = createTournamentsService(pb);
const matchesService = createMatchesService(pb);
const workbook = xlsx.readFile(EXCEL_FILE_PATH);
let teamIdMap = {};
let tournamentIdMap = {};
// Process sheets in correct order: Tournaments -> Teams -> Matches
const sheetOrder = ["tournament", "tournaments", "teams", "matches"];
const processedSheets = new Set();
for (const sheetNamePattern of sheetOrder) {
for (const sheetName of workbook.SheetNames) {
if (processedSheets.has(sheetName)) continue;
if (sheetName.toLowerCase() !== sheetNamePattern) continue;
const worksheet = workbook.Sheets[sheetName];
const rows = xlsx.utils.sheet_to_json(worksheet);
console.log(`\n📘 Processing sheet: ${sheetName}`);
switch (sheetName.toLowerCase()) {
case "teams":
teamIdMap = await handleTeamsSheet(rows, teamsService, playersService, pb, tournamentIdMap);
break;
case "tournament":
case "tournaments":
tournamentIdMap = await handleTournamentSheet(rows, tournamentsService, teamIdMap, pb);
break;
case "matches":
await handleMatchesSheet(rows, matchesService, teamIdMap, tournamentIdMap, pb);
break;
default:
console.log(`⚠️ No handler found for sheet '${sheetName}', skipping.`);
}
processedSheets.add(sheetName);
}
}
console.log("\n🎉 All sheets imported successfully!");
}
// --- Run ---
importExcel().catch(console.error);