import { db } from '$lib/server/db'; import { character, devilFruit, devilFruitHistory, type DevilFruit, type Character, type DevilFruitType } from '$lib/server/db/schema'; import { eq, and } from 'drizzle-orm'; const characterWithFruitSelect = { id: character.id, name: character.name, frName: character.frName, devilFruitId: character.devilFruitId, devilFruitName: devilFruit.name, devilFruitType: devilFruit.type, // include url if available from devilFruit join url: devilFruit.url }; export type CharacterWithFruit = Pick & { devilFruitName: string | null; devilFruitType: DevilFruitType | null; frName: string | null; url: string | null; }; export function getDateKey(date: Date): number { return normalizeDay(date).getTime(); } export function normalizeDay(date: Date = new Date()): Date { const normalized = new Date(date); normalized.setHours(1, 0, 0, 0); return normalized; } function pickDailyFruit(fruits: DevilFruit[]): DevilFruit { const randomIndex = Math.floor(Math.random() * fruits.length); return fruits[randomIndex]; } export async function getCharactersWithDevilFruit(): Promise { const rows = await db .select(characterWithFruitSelect) .from(character) .leftJoin(devilFruit, eq(character.devilFruitId, devilFruit.id)) .where(eq(character.isInDailyMode, true)) .all(); return rows.filter((r): r is CharacterWithFruit => Boolean(r.devilFruitId)); } export async function getAllDevilFruitsFromCharacters(): Promise { const characters = await db .select(characterWithFruitSelect) .from(character) .leftJoin(devilFruit, eq(character.devilFruitId, devilFruit.id)) .where(eq(character.isInDailyMode, true)) .all(); const map = new Map(); for (const row of characters) { if (row.devilFruitId && row.devilFruitName) { if (!map.has(row.devilFruitId)) { map.set(row.devilFruitId, { id: row.devilFruitId, name: row.devilFruitName, type: row.devilFruitType ?? 'Unknown', url: row.url ?? null } as DevilFruit); } } } return Array.from(map.values()); } export async function getFruitById(fruitId: string): Promise { const [found] = await db.select().from(devilFruit).where(eq(devilFruit.id, fruitId)).limit(1); return (found as DevilFruit) ?? null; } export async function getOrCreateTodayFruit(date: Date = new Date()): Promise { const today = normalizeDay(date); const todayDate = getDateKey(today); const [existingEntry] = await db .select() .from(devilFruitHistory) .where(eq(devilFruitHistory.date, todayDate)) .limit(1); if (existingEntry?.devilFruitId) { return getFruitById(existingEntry.devilFruitId); } const allFruits = await getAllDevilFruitsFromCharacters(); if (allFruits.length === 0) return null; const chosen = pickDailyFruit(allFruits); try { await db.insert(devilFruitHistory).values({ devilFruitId: chosen.id, date: todayDate, createdAt: Date.now(), updatedAt: Date.now() }); } catch (error) { console.error('Failed to record daily fruit:', error); } return chosen; } export async function getYesterdayFruit(date: Date = new Date()): Promise { const yesterday = new Date(date); yesterday.setDate(yesterday.getDate() - 1); const yesterdayDate = getDateKey(yesterday); const [yesterdayEntry] = await db .select() .from(devilFruitHistory) .where(eq(devilFruitHistory.date, yesterdayDate)) .limit(1); if (!yesterdayEntry?.devilFruitId) return null; return getFruitById(yesterdayEntry.devilFruitId); } export async function getTodayFruitWinsCount(fruitId: string, date: Date = new Date()): Promise { const today = normalizeDay(date); const todayDate = getDateKey(today); const [result] = await db .select({ won: devilFruitHistory.won }) .from(devilFruitHistory) .where(and(eq(devilFruitHistory.devilFruitId, fruitId), eq(devilFruitHistory.date, todayDate))); return result?.won ?? 0; }