import { db } from './index'; import type { PicletInstance } from './schema'; import { PicletType } from '../types/picletTypes'; import type { PicletStats } from '../types'; import { generatePicletId } from '../utils/picletId'; import type { UserInfo } from '../stores/auth'; // Interface for generated piclet data (from PicletResult component) interface GeneratedPicletData { name: string; imageUrl: string; imageData?: string; imageCaption: string; concept: string; imagePrompt: string; stats: PicletStats; createdAt: Date; } /** * Convert generated piclet data to a PicletInstance * @param data - The generated piclet data with stats and images * @param objectName - Optional normalized object name (e.g., "eiffel tower") * @param attributes - Optional array of variation attributes (first item is the primary variation) * @param visualDetails - Optional additional visual details * @param userInfo - Optional HF user info for discoverer attribution */ export async function generatedDataToPicletInstance( data: GeneratedPicletData, objectName?: string, attributes?: string[], visualDetails?: string, userInfo?: UserInfo | null ): Promise> { if (!data.stats) { throw new Error('Generated data must have stats to create PicletInstance'); } const stats = data.stats as PicletStats; // Map tier from stats to discovery rarity let tier: string = stats.tier || 'common'; // Generate typeId using normalized object name + variation (first attribute if any) // Variation is "canonical" if there are no attributes or if first attribute is "canonical" const normalizedObjectName = objectName || stats.name; const variation = attributes && attributes.length > 0 ? attributes[0] : undefined; const typeId = generatePicletId(normalizedObjectName, variation && variation !== 'canonical' ? variation : undefined); return { // Basic Info typeId: typeId, objectName: objectName || stats.name || data.name, nickname: stats.name || data.name, primaryType: stats.primaryType as PicletType, tier: tier, // Discovery Metadata isCanonical: false, // Will be set by server canonicalId: undefined, variationAttributes: attributes || [], // Populate discoverer info from auth if available discoveredBy: userInfo?.preferred_username || 'Player', // Legacy field discovererSub: userInfo?.sub, discovererUsername: userInfo?.preferred_username, discovererName: userInfo?.name, discovererPicture: userInfo?.picture, discoveredAt: new Date(), scanCount: 1, // Collection Management isInCollection: true, // Auto-collected when scanned collectedAt: new Date(), // Visual Data imageUrl: data.imageUrl, imageData: data.imageData, imageCaption: data.imageCaption, visualDetails: visualDetails || '', concept: data.concept, description: stats.description, imagePrompt: data.imagePrompt }; } // Save a piclet instance to the database export async function savePicletInstance(picletInstance: Omit): Promise { const id = await db.picletInstances.add(picletInstance as any); return id; } // Update a piclet instance in the database export async function updatePicletInstance(id: number, updates: Partial): Promise { await db.picletInstances.update(id, updates); } // Delete a piclet instance from the database export async function deletePicletInstance(id: number): Promise { await db.picletInstances.delete(id); } // Get all piclet instances export async function getAllPicletInstances(): Promise { return await db.picletInstances.toArray(); } // Get a single piclet instance by ID export async function getPicletInstance(id: number): Promise { return await db.picletInstances.get(id); } // Get collected piclets (those that have been discovered) export async function getCollectedPiclets(): Promise { const allRecords = await db.picletInstances.toArray(); return allRecords.filter(p => p.isInCollection === true); } // Get canonical piclets export async function getCanonicalPiclets(): Promise { // Use filter for boolean fields to avoid index issues const allRecords = await db.picletInstances.toArray(); return allRecords.filter(p => p.isCanonical === true); } // Get piclets by object name export async function getPicletsByObjectName(objectName: string): Promise { return await db.picletInstances.where('objectName').equals(objectName).toArray(); } // Get variations of a canonical piclet export async function getVariations(canonicalId: string): Promise { return await db.picletInstances.where('canonicalId').equals(canonicalId).toArray(); } // Update scan count export async function updateScanCount(picletId: number): Promise { const piclet = await db.picletInstances.get(picletId); if (piclet) { await db.picletInstances.update(picletId, { scanCount: (piclet.scanCount || 0) + 1 }); } }