Fraser commited on
Commit
2aa7dab
Β·
1 Parent(s): 5056db8
src/lib/db/trainerScanning.ts CHANGED
@@ -8,43 +8,60 @@ export async function initializeTrainerScanProgress(imagePaths: string[]): Promi
8
  const tx = db.transaction([TRAINER_SCAN_STORE], 'readwrite');
9
  const store = tx.objectStore(TRAINER_SCAN_STORE);
10
 
 
 
 
11
  for (const imagePath of imagePaths) {
12
- // Extract trainer name and image index from path
13
- // Format: "trainer_images/001_Willow_Snap/image_001.jpg"
14
- const pathParts = imagePath.split('/');
15
- if (pathParts.length < 3) {
16
- console.warn(`Skipping invalid path format: ${imagePath}`);
17
- continue;
18
- }
19
-
20
- const trainerName = pathParts[1]; // "001_Willow_Snap"
21
- const imageFile = pathParts[2]; // "image_001.jpg"
22
-
23
- if (!trainerName || !imageFile) {
24
- console.warn(`Skipping path with missing parts: ${imagePath}`);
25
- continue;
26
- }
27
-
28
- const imageMatch = imageFile.match(/image_(\d+)\.jpg/);
29
- const imageIndex = imageMatch ? parseInt(imageMatch[1]) : 1;
30
-
31
- const remoteUrl = `https://huggingface.co/datasets/Fraser/piclets/resolve/main/${imagePath}`;
32
-
33
- // Check if this path already exists
34
- const existing = await store.get(imagePath);
35
- if (!existing) {
36
- const progressRecord: Omit<TrainerScanProgress, 'id'> = {
37
- imagePath,
38
- trainerName,
39
- imageIndex,
40
- status: 'pending',
41
- remoteUrl
42
- };
43
 
44
- await store.add(progressRecord);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  }
46
  }
47
 
 
 
48
  await tx.complete;
49
  }
50
 
 
8
  const tx = db.transaction([TRAINER_SCAN_STORE], 'readwrite');
9
  const store = tx.objectStore(TRAINER_SCAN_STORE);
10
 
11
+ let processedCount = 0;
12
+ let skippedCount = 0;
13
+
14
  for (const imagePath of imagePaths) {
15
+ try {
16
+ // Extract trainer name and image index from path
17
+ // Format: "trainer_images/001_Willow_Snap/image_001.jpg"
18
+ const pathParts = imagePath.split('/');
19
+ if (pathParts.length < 3) {
20
+ console.warn(`⚠️ Skipping invalid path format: ${imagePath}`);
21
+ skippedCount++;
22
+ continue;
23
+ }
24
+
25
+ const trainerName = pathParts[1]?.trim(); // "001_Willow_Snap"
26
+ const imageFile = pathParts[2]?.trim(); // "image_001.jpg"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
+ if (!trainerName || !imageFile || typeof trainerName !== 'string' || typeof imageFile !== 'string') {
29
+ console.warn(`⚠️ Skipping path with missing or invalid parts: ${imagePath}`, { trainerName, imageFile });
30
+ skippedCount++;
31
+ continue;
32
+ }
33
+
34
+ const imageMatch = imageFile.match(/image_(\d+)\.jpg/);
35
+ const imageIndex = imageMatch ? parseInt(imageMatch[1]) : 1;
36
+
37
+ const remoteUrl = `https://huggingface.co/datasets/Fraser/piclets/resolve/main/${imagePath}`;
38
+
39
+ // Check if this path already exists to avoid duplicates
40
+ const existing = await store.get(imagePath);
41
+ if (!existing) {
42
+ const progressRecord: Omit<TrainerScanProgress, 'id'> = {
43
+ imagePath,
44
+ trainerName,
45
+ imageIndex,
46
+ status: 'pending',
47
+ remoteUrl
48
+ };
49
+
50
+ await store.add(progressRecord);
51
+ processedCount++;
52
+ } else {
53
+ // Record exists, don't count as processed but note it
54
+ processedCount++;
55
+ }
56
+ } catch (error) {
57
+ console.error(`❌ Failed to process path entry: ${imagePath}`, error);
58
+ skippedCount++;
59
+ // Continue processing other paths despite this failure
60
  }
61
  }
62
 
63
+ console.log(`βœ… Trainer scan initialization complete: ${processedCount} records processed, ${skippedCount} skipped`);
64
+
65
  await tx.complete;
66
  }
67
 
src/lib/services/trainerScanService.ts CHANGED
@@ -134,6 +134,16 @@ export class TrainerScanService {
134
  } finally {
135
  this.isScanning = false;
136
  this.notifyStateChange({ isScanning: false, currentImage: null, currentTrainer: null });
 
 
 
 
 
 
 
 
 
 
137
  }
138
  }
139
 
@@ -154,19 +164,28 @@ export class TrainerScanService {
154
 
155
  this.notifyStateChange({
156
  currentImage: nextImage.imagePath,
157
- currentTrainer: nextImage.trainerName
158
  });
159
 
160
  try {
161
  await this.processImage(nextImage.imagePath, nextImage.remoteUrl);
 
162
  // Add small delay between images to prevent overwhelming the system
163
  await new Promise(resolve => setTimeout(resolve, 1000));
164
  } catch (error) {
165
- console.error(`Failed to process ${nextImage.imagePath}:`, error);
166
- await markImageProcessingFailed(
167
- nextImage.imagePath,
168
- error instanceof Error ? error.message : 'Unknown error'
169
- );
 
 
 
 
 
 
 
 
170
  }
171
 
172
  // Update progress
@@ -179,27 +198,35 @@ export class TrainerScanService {
179
  await markImageProcessingStarted(imagePath);
180
 
181
  try {
 
182
  // Fetch remote image
183
  const imageFile = await this.fetchRemoteImage(remoteUrl, imagePath);
184
 
 
185
  // Caption the image
186
  const imageCaption = await this.captionImage(imageFile);
187
 
 
188
  // Generate monster concept
189
  const picletConcept = await this.generatePicletConcept(imageCaption);
190
 
 
191
  // Generate stats
192
  const picletStats = await this.generatePicletStats(picletConcept);
193
 
 
194
  // Generate image prompt
195
  const imagePrompt = await this.generateImagePrompt(picletConcept);
196
 
 
197
  // Generate monster image
198
  const picletImageUrl = await this.generateMonsterImage(imagePrompt);
199
 
 
200
  // Process generated image (remove background)
201
  const imageData = await this.processGeneratedImage(picletImageUrl);
202
 
 
203
  // Create piclet instance
204
  const generatedData = {
205
  name: this.extractNameFromConcept(picletConcept),
@@ -218,7 +245,10 @@ export class TrainerScanService {
218
  await markImageProcessingCompleted(imagePath, savedId);
219
 
220
  } catch (error) {
221
- throw error; // Re-throw to be caught by processingLoop
 
 
 
222
  }
223
  }
224
 
 
134
  } finally {
135
  this.isScanning = false;
136
  this.notifyStateChange({ isScanning: false, currentImage: null, currentTrainer: null });
137
+
138
+ // Log final summary
139
+ const finalStats = await getScanningStats();
140
+ console.log(`🏁 Scanning session complete:`, {
141
+ total: finalStats.total,
142
+ completed: finalStats.completed,
143
+ failed: finalStats.failed,
144
+ pending: finalStats.pending,
145
+ successRate: finalStats.total > 0 ? Math.round((finalStats.completed / finalStats.total) * 100) + '%' : '0%'
146
+ });
147
  }
148
  }
149
 
 
164
 
165
  this.notifyStateChange({
166
  currentImage: nextImage.imagePath,
167
+ currentTrainer: typeof nextImage.trainerName === 'string' ? nextImage.trainerName : null
168
  });
169
 
170
  try {
171
  await this.processImage(nextImage.imagePath, nextImage.remoteUrl);
172
+ console.log(`βœ… Successfully processed: ${nextImage.imagePath} (${nextImage.trainerName})`);
173
  // Add small delay between images to prevent overwhelming the system
174
  await new Promise(resolve => setTimeout(resolve, 1000));
175
  } catch (error) {
176
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
177
+ console.error(`❌ Failed to process ${nextImage.imagePath} (${nextImage.trainerName}):`, {
178
+ imagePath: nextImage.imagePath,
179
+ trainerName: nextImage.trainerName,
180
+ remoteUrl: nextImage.remoteUrl,
181
+ error: errorMessage,
182
+ fullError: error
183
+ });
184
+
185
+ await markImageProcessingFailed(nextImage.imagePath, errorMessage);
186
+
187
+ // Continue to next image - don't let individual failures stop the whole process
188
+ console.log(`πŸ”„ Continuing to next image despite failure...`);
189
  }
190
 
191
  // Update progress
 
198
  await markImageProcessingStarted(imagePath);
199
 
200
  try {
201
+ console.log(`πŸ”„ Processing ${imagePath}: Fetching remote image...`);
202
  // Fetch remote image
203
  const imageFile = await this.fetchRemoteImage(remoteUrl, imagePath);
204
 
205
+ console.log(`πŸ”„ Processing ${imagePath}: Captioning image...`);
206
  // Caption the image
207
  const imageCaption = await this.captionImage(imageFile);
208
 
209
+ console.log(`πŸ”„ Processing ${imagePath}: Generating concept...`);
210
  // Generate monster concept
211
  const picletConcept = await this.generatePicletConcept(imageCaption);
212
 
213
+ console.log(`πŸ”„ Processing ${imagePath}: Generating stats...`);
214
  // Generate stats
215
  const picletStats = await this.generatePicletStats(picletConcept);
216
 
217
+ console.log(`πŸ”„ Processing ${imagePath}: Generating image prompt...`);
218
  // Generate image prompt
219
  const imagePrompt = await this.generateImagePrompt(picletConcept);
220
 
221
+ console.log(`πŸ”„ Processing ${imagePath}: Generating monster image...`);
222
  // Generate monster image
223
  const picletImageUrl = await this.generateMonsterImage(imagePrompt);
224
 
225
+ console.log(`πŸ”„ Processing ${imagePath}: Processing generated image...`);
226
  // Process generated image (remove background)
227
  const imageData = await this.processGeneratedImage(picletImageUrl);
228
 
229
+ console.log(`πŸ”„ Processing ${imagePath}: Creating piclet instance...`);
230
  // Create piclet instance
231
  const generatedData = {
232
  name: this.extractNameFromConcept(picletConcept),
 
245
  await markImageProcessingCompleted(imagePath, savedId);
246
 
247
  } catch (error) {
248
+ // Add context about which step failed
249
+ const enhancedError = new Error(`Failed during processing of ${imagePath}: ${error instanceof Error ? error.message : 'Unknown error'}`);
250
+ enhancedError.cause = error;
251
+ throw enhancedError;
252
  }
253
  }
254