File size: 5,110 Bytes
b66ef35
c703ea3
 
ac7c05c
fba600d
82f6d8e
b66ef35
8db63ba
 
 
 
 
 
 
 
 
 
 
 
b78dca2
 
 
 
 
 
82f6d8e
b78dca2
565e57b
 
 
 
82f6d8e
 
565e57b
8db63ba
 
 
 
 
565e57b
 
 
 
b78dca2
 
fba600d
b78dca2
fba600d
565e57b
8db63ba
c703ea3
565e57b
 
c703ea3
 
 
565e57b
 
 
 
 
82f6d8e
 
 
 
 
 
565e57b
 
 
 
 
 
 
 
8db63ba
 
 
565e57b
8db63ba
 
 
 
 
 
c703ea3
 
 
 
b66ef35
 
c703ea3
 
 
5fe1a3d
 
c703ea3
 
 
5fe1a3d
 
c703ea3
b66ef35
 
 
 
c703ea3
 
 
 
 
565e57b
 
02172be
6c2bc5a
b66ef35
 
565e57b
 
bf06454
 
 
21805fd
 
565e57b
 
 
c703ea3
 
565e57b
 
 
21805fd
 
565e57b
 
 
 
 
 
 
 
b66ef35
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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<Omit<PicletInstance, 'id'>> {
  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<PicletInstance, 'id'>): Promise<number> {
  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<PicletInstance>): Promise<void> {
  await db.picletInstances.update(id, updates);
}

// Delete a piclet instance from the database
export async function deletePicletInstance(id: number): Promise<void> {
  await db.picletInstances.delete(id);
}

// Get all piclet instances
export async function getAllPicletInstances(): Promise<PicletInstance[]> {
  return await db.picletInstances.toArray();
}

// Get a single piclet instance by ID
export async function getPicletInstance(id: number): Promise<PicletInstance | undefined> {
  return await db.picletInstances.get(id);
}

// Get collected piclets (those that have been discovered)
export async function getCollectedPiclets(): Promise<PicletInstance[]> {
  const allRecords = await db.picletInstances.toArray();
  return allRecords.filter(p => p.isInCollection === true);
}

// Get canonical piclets
export async function getCanonicalPiclets(): Promise<PicletInstance[]> {
  // 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<PicletInstance[]> {
  return await db.picletInstances.where('objectName').equals(objectName).toArray();
}

// Get variations of a canonical piclet
export async function getVariations(canonicalId: string): Promise<PicletInstance[]> {
  return await db.picletInstances.where('canonicalId').equals(canonicalId).toArray();
}

// Update scan count
export async function updateScanCount(picletId: number): Promise<void> {
  const piclet = await db.picletInstances.get(picletId);
  if (piclet) {
    await db.picletInstances.update(picletId, {
      scanCount: (piclet.scanCount || 0) + 1
    });
  }
}