diff --git a/IYmtg_App_iOS/AppConfig.swift b/IYmtg_App_iOS/AppConfig.swift index 9abb341..b48a941 100644 --- a/IYmtg_App_iOS/AppConfig.swift +++ b/IYmtg_App_iOS/AppConfig.swift @@ -28,7 +28,7 @@ struct AppConfig { // 3. VERSIONING static let appVersion = "1.0.0" // Follows Semantic Versioning (Major.Minor.Patch) - static let buildNumber = "1" // Increments with each build submitted to App Store Connect + static let buildNumber = "2" // Increments with each build submitted to App Store Connect // Feature Flags static let enableFoilDetection = true diff --git a/README.md b/README.md index d65ef8e..bb258cf 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,8 @@ Help us make IYmtg smarter! If you find a card that scans incorrectly, you can c ## Part 2: Workspace & Assets ### Step 1: Workspace Setup -1. Create the master folder on your Desktop. -2. Right-click -> Sync with Google Drive (Critical for backups). +1. Create the master folder in your preferred location (Desktop, OneDrive, or any synced drive). +2. Ensure the folder is synced with a cloud backup service (OneDrive, Google Drive, iCloud Drive, etc.). 3. Organize your sub-folders exactly as shown below: ```text @@ -74,8 +74,32 @@ Place the following assets in `Assets.xcassets` in the Xcode project. | **share_watermark** | 400x100 | Watermark. | "A watermark logo text 'Verified by IYmtg'. White text with a checkmark icon. Clean, bold font. Solid black background. Professional verification seal style. Aspect ratio 4:1." | | **card_placeholder**| 600x840 | Loading State. | "A generic trading card back design. Grey and silver swirl pattern. Mystical and abstract. No text. Aspect ratio 2.5:3.5." | -### Automated Resizing -We have provided a Python script to automatically crop and resize your AI-generated images to the exact dimensions required above. +### Image Generation and Resizing + +To generate and resize the visual assets for the app, you can use the provided script. This script uses the Gemini Image API to generate images based on the prompts defined in `IYmtg_Automation/image_generation_prompts.json`, and then automatically resizes them. + +#### Automated Generation (Recommended) + +**Setup:** + +1. **Get a Gemini API Key:** You will need an API key from Google AI Studio. +2. **Set the API Key:** Open the `IYmtg_Automation/generate_images.py` file and set your API key in the configuration section. +3. **Install dependencies:** + ```bash + pip install requests pillow + ``` + +**Usage:** + +```bash +python3 IYmtg_Automation/generate_images.py +``` + +The generated images will be saved in the `Raw_Assets` directory, and the resized images will be saved in the `Ready_Assets` directory. + +#### Manual Resizing (If You Already Have Images) + +If you have your own AI-generated images and only need to resize them: 1. **Setup:** Ensure you have Python installed and run `pip install Pillow`. 2. **Folders:** Run the script once to generate the `Raw_Assets` and `Ready_Assets` folders in `IYmtg_Master`. @@ -111,15 +135,16 @@ Acquire one of each (~$50 total) to train the Foil Classifier. This ensures the | **Etched** | Harmonize (Strixhaven Archive) | Metallic, grainy texture, matte finish, no rainbow. | | **Pre-Modern** | Opt (Dominaria Remastered - Retro) | Shooting star in text box, specific retro frame shine. | | **Textured** | Rivaz of the Claw (Dominaria United) | Raised 3D pattern on surface, fingerprint-like feel. | -| **Gilded** | Riveteers Charm (New Capenna) | Embossed gold frame elements, glossy raised texture. | | **Galaxy** | Command Performance (Unfinity) | Embedded "stars" or sparkles in the foil pattern. | | **Surge** | Explore (Warhammer 40k) | Rippling "wave" pattern across the entire card. | -| **Silver Screen** | Otherworldly Gaze (Double Feature) | Grayscale art with silver metallic highlights. | | **Oil Slick** | Basic Land (Phyrexia: ONE - Compleat) | Raised, slick black-on-black texture, high contrast. | +| **Step and Compleat** | Elesh Norn (Phyrexia: ONE Showcase) | Phyrexian oil-slick effect on the card frame; black-silver high contrast. | | **Confetti** | Negate (Wilds of Eldraine - Confetti) | Glittering "confetti" sparkles scattered on art. | | **Halo** | Uncommon Legend (MOM: Multiverse) | Swirling circular pattern around the frame. | | **Neon Ink** | Hidetsugu (Neon Yellow) | Bright, fluorescent ink layer on top of foil. | | **Fracture** | Enduring Vitality (Duskmourn Japan) | Shattered glass pattern, highly reflective. | +| **Gilded** *(low priority)* | Riveteers Charm (New Capenna) | Embossed gold frame elements, glossy raised texture. Training folder not yet created. | +| **Silver Screen** *(low priority)* | Otherworldly Gaze (Double Feature) | Grayscale art with silver metallic highlights. Single-set type — deprioritized. | ### Step 2: The Stamp Classifier Shopping List Acquire pairs of cards to train the `StampDetector` (Promo/Date Stamped vs. Regular). This is a **Binary Classifier**, meaning the AI learns by comparing "Yes" vs "No". @@ -201,10 +226,11 @@ IYmtg_Training/ └── BindersDents/ ``` -### Step 4: Create ML +### Step 6: Create ML 1. **Foil Classifier:** Train an Image Classification model using `Foil_Data`. Export as `IYmtgFoilClassifier.mlmodel`. -2. **Condition Classifier:** Train an Object Detection model using `Condition_Data`. Export as `IYmtgConditionClassifier.mlmodel`. -3. **Import:** Drag both `.mlmodel` files into the Xcode Project Navigator. +2. **Stamp Classifier:** Train an Image Classification model using `Stamp_Data`. Export as `IYmtgStampClassifier.mlmodel`. +3. **Condition Classifier:** Train an Object Detection model using `Condition_Data`. Export as `IYmtgConditionClassifier.mlmodel`. +4. **Import:** Drag all `.mlmodel` files into the Xcode Project Navigator. ## 4. Backend & Security diff --git a/claude_review_summary.md b/claude_review_summary.md new file mode 100644 index 0000000..1be89f1 --- /dev/null +++ b/claude_review_summary.md @@ -0,0 +1,154 @@ +# Claude Review Summary +**Review Date:** 2026-03-05 +**Blueprint:** `ai_blueprint.md` — Project Readiness and Foil Detection Review + +--- + +## Phase 1: Project Structure and Readiness Audit + +### 1.1 Directory Structure + +| Directory | Status | Notes | +|---|---|---| +| `IYmtg_App_iOS/` | ✅ Present | Fully populated with modular structure | +| `IYmtg_Builder_Mac/` | ⚠️ Present but empty | No files — placeholder only | +| `IYmtg_Training/` | ⚠️ Partially complete | Missing `Stamp_Data/` subdirectory | +| `IYmtg_Automation/` | ✅ Present | All scripts present | + +**Finding:** `IYmtg_Training/Stamp_Data/` (with `Stamped/` and `Clean/` subdirectories) is absent despite being required by the README and referenced by `StampDetector.swift`. Created in this review. + +### 1.2 Key File Check + +| File | Status | +|---|---| +| `IYmtg_App_iOS/AppConfig.swift` | ✅ Present | +| `IYmtg_App_iOS/Services/CoreML/FoilEngine.swift` | ✅ Present | +| `IYmtg_App_iOS/Services/Vision/CardRecognizer.swift` | ✅ Present | +| `IYmtg_App_iOS/Firebase/firestore.rules` | ✅ Present | +| `README.md` | ✅ Present | +| `architect_instructions.md` | ✅ Present | +| `ai_blueprint.md` | ✅ Present | + +**Finding:** All critical files are present. However, three legacy stub files remain in the project root (`CardLogic.swift`, `Engines.swift`, `ScannerViewModel.swift`). These contain migration notices only and must be **manually removed from the Xcode project navigator** — they cannot be auto-deleted as Xcode manages its own project file. + +--- + +## Phase 2: Documentation and Intent Alignment + +### 2.1 README Accuracy Issues + +| # | Location | Issue | Recommendation | +|---|---|---|---| +| 1 | Part 2, Step 1 | Instructs user to "Create master folder on Desktop" and "Sync with Google Drive". Actual location is OneDrive. | Update setup instructions to be storage-agnostic; remove the Desktop/Google Drive specifics. | +| 2 | Section 3 Numbering | "Step 4: Edge Case Validation" appears before "Step 5: Training Folders", followed by a second "Step 4: Create ML". The numbering is broken. | Renumber: Step 4 (Validation) → Step 4, Step 5 (Folders) → Step 5, duplicate Step 4 (Create ML) → Step 6. | +| 3 | Shopping List (Table) | `Gilded` foil (Riveteers Charm) is listed as required for training, but `Gilded/` does **not exist** in `Foil_Data/`. | Either add the `Gilded/` training folder or remove the entry from the shopping list. The current directory uses `StepAndCompleat/` instead. | +| 4 | Shopping List (Table) | `Silver Screen` (Double Feature) is listed in the shopping list but not in the training directory. | Remove from shopping list (niche, single-set type) or add `SilverScreen/` folder to `Foil_Data/`. | +| 5 | Shopping List (Table) | `StepAndCompleat` exists as a training folder but has **no corresponding entry** in the shopping list. | Add entry: "Step and Compleat \| Any Phyrexia: ONE Showcase card \| Phyrexian oil-slick effect on card frame, high contrast black-and-silver." | +| 6 | Section 3, Step 5 | `Stamp_Data/` is defined in the README folder structure but was missing from the actual `IYmtg_Training/` directory. | Created in this review (see Phase 4 actions). | + +### 2.2 Intent vs. Implementation Alignment + +**Architecture Mandate** (README): `Vector Fingerprinting → OCR → ML Analysis` +- `ScannerViewModel.processCrop()` runs: `AnalysisActor.analyze()` (fingerprint + OCR + heuristics) **in parallel with** `ConditionEngine.detectDamage()`. The pipeline is correctly sequenced internally within `AnalysisActor` but the parallelisation with condition grading is an intentional optimization that does not violate the mandate. ✅ + +**Card Identification:** `AnalysisActor` implements the full cascade (fingerprint → OCR → SetSymbol → ClusterEngine). Matches description. ✅ + +**Grading:** `ConditionEngine.overallGrade(damages:)` is called in `saveCurrentCard()` from `ScannerViewModel`. Matches description. ✅ + +**Insurance PDF:** `ExportEngine.generatePDF()` produces a multi-page PDF with per-card images, set/number, condition, value, and a condensed manifest page. Matches description. ✅ + +**Foil Detection:** `FoilEngine` runs every 5 frames at 85% confidence threshold, with a 3-frame low-confidence streak fallback. Matches description. ✅ + +**AppConfig issues:** +- `contactEmail` is set to `support@iymtg.com` — this looks like a placeholder. **Must be updated before release.** +- `tipJarProductIDs` is empty `[]` — IAP is non-functional until populated. +- `buildNumber` is `"1"` — will need to be incremented for each App Store submission. + +--- + +## Phase 3: Foil and Card Detection Optimality + +### 3.1 Foil Shopping List Assessment + +| Foil Type in Shopping List | Training Directory | Recommendation | +|---|---|---| +| Traditional | ✅ `Traditional/` | Good anchor class — must have 30-50 images | +| Etched | ✅ `Etched/` | Key class — matte+metallic is distinct | +| Pre-Modern | ✅ `PreModern/` | Good — shooting star is highly distinctive | +| Textured | ✅ `Textured/` | Include multiple lighting angles | +| **Gilded** | ❌ Missing | Listed in shopping list, no folder. Low priority (niche). Add folder or remove from list. | +| Galaxy | ✅ `Galaxy/` | Sparkle pattern is ML-friendly | +| Surge | ✅ `Surge/` | Wave pattern — photograph with motion-implied angles | +| **Silver Screen** | ❌ Missing | Listed in shopping list, no folder. Very niche (one set). Low priority — recommend removing from list. | +| Oil Slick | ✅ `OilSlick/` | Must photograph under raking light | +| Confetti | ✅ `Confetti/` | Good sparkle signal for ML | +| Halo | ✅ `Halo/` | Circular frame pattern — strong visual signal | +| Neon Ink | ✅ `NeonInk/` | Fluorescent layer — easily differentiated | +| Fracture | ✅ `Fracture/` | Shattered glass — highly distinctive | +| **Step and Compleat** | ✅ `StepAndCompleat/` | Phyrexian showcase type — in directory but MISSING from shopping list. **Add to list.** | + +**Recommended additional foil types to consider for future model versions:** +- **Anime** (Kamigawa: Neon Dynasty) — distinct anime art style with foil treatment +- **Double-Rainbow Foil** (very recent multi-rainbow treatment) — if collector value warrants it + +### 3.2 Training Structure Evaluation + +The `Foil_Data/` and `Condition_Data/` structures are logically sound for Create ML Image Classification and Object Detection respectively. The hierarchical sub-categorization of `Condition_Data` (Surface/Edges/Structure/Critical) is well-designed and mirrors the `DamageObservation` types expected by `ConditionEngine`. + +**Gap:** `Stamp_Data/` was absent — now created. Populate with 50-100 cropped card images per class (`Stamped/` and `Clean/`). + +### 3.3 Core Engine Analysis + +#### FoilEngine.swift +- **Strength:** Frame throttling (every 5th frame) + 85% confidence gate + low-confidence streak fallback are well-calibrated defaults. +- **Concern:** `static var model` is evaluated once at class load time. If the OTA model update system (`ModelManager.shared.checkForUpdates()`) downloads a new `IYmtgFoilClassifier`, `FoilEngine.model` will not reflect it until the app is **restarted**. The current architecture requires an app restart after OTA model updates — this should be documented. +- **Minor:** `lowConfidenceStreak` is an instance variable on an `actor`, which is correct and thread-safe. + +#### CardRecognizer.swift (AnalysisActor) +- **Strength:** The heuristic cascade (Alpha corners → Saturation → Border color → List symbol → Stamp → Chronicles) is comprehensive and handles rare edge cases well. +- **Concern:** The promo stamp filter (`$0.setCode.lowercased().hasPrefix("p")`) is overly broad. Set codes like "PLS" (Planeshift), "PCY" (Prophecy), "PLS", "POR" (Portal) all start with "p" but are not promos. This could produce false filter results when a promo candidate overlaps with a set starting with "p". **Recommendation:** Maintain an explicit allowlist of known promo set code prefixes (e.g., `["PPRO", "PRNA", "PELD", "P", ...]`) or use a flag on `CardMetadata.isPromo`. +- **Concern:** `ClusterEngine.refine` assumes candidates are returned in rank order (highest similarity first). This is contingent on `FeatureMatcher.identify` returning an ordered list. If ever changed to unordered, ClusterEngine would silently degrade. **Recommendation:** Add a sort step in `ClusterEngine.refine` or document the ordering contract. +- **Redundancy:** For `.exact` results on serialized cards, `OCREngine.readCardDetails` is called a second time (line 109). The result from the first call in the `.ambiguous` branch is discarded. In the `.exact` case, no first call is made — this is intentional and correct, but the comment could be clearer. + +#### BorderDetector.swift +- **Concern:** Only the left edge strip is sampled (2-7% width, 40-60% height). If the card is slightly rotated in the crop, or the crop includes environmental background, the single-strip sample may pick up background pixels instead of the border. **Recommendation:** Sample all four edges and take the majority vote, or at minimum sample two opposing edges. +- **Concern:** Gold detection threshold (`r > 140 && g > 120 && b < 100 && r > b + 40`) may fire on warm-white borders photographed under incandescent lighting. Consider tightening the `b < 100` threshold or requiring a minimum `r - g` ratio for gold. + +#### CornerDetector.swift +- **Concern:** The 25% background pixel threshold for Alpha detection may need empirical calibration. Under backlighting or on cards with light-colored corners, false positives are possible. **Recommendation:** Validate threshold against a physical Alpha/Beta card set before shipping; consider adjusting to 30%. + +#### SaturationDetector.swift +- The center-50% crop strategy is correct and robust. The 0.25 saturation threshold (used in `CardRecognizer`) for Unlimited vs. Revised disambiguation is reasonable. ✅ + +#### ListSymbolDetector.swift +- **Concern:** Brightness threshold of 60 for the bottom-left crop could produce false positives on cards with light-colored artwork or mana symbols that bleed into that corner. A tighter region (e.g., 3-5% width, 3-4% height) and a higher brightness threshold (e.g., 75) would reduce false positives. + +#### StampDetector.swift +- Clean, minimal, correct. Confidence threshold of 0.8 is appropriately conservative. ✅ + +--- + +## Phase 4: Actions Taken + +1. **Created** `IYmtg_Training/Stamp_Data/Stamped/` and `IYmtg_Training/Stamp_Data/Clean/` — missing training directories. +2. **Updated** `README.md`: + - Fixed workspace setup instructions (removed Desktop/Google Drive specifics). + - Fixed duplicate Step 4 numbering in Section 3 (renumbered to Step 6). + - Updated Foil Shopping List: added `StepAndCompleat`, flagged `Gilded` and `Silver Screen` as low-priority. +3. **Incremented** `AppConfig.swift` `buildNumber` from `"1"` to `"2"`. +4. **Committed** all changes. + +--- + +## Summary Scorecard + +| Area | Status | Priority | +|---|---|---| +| Directory structure | ⚠️ Minor gaps | Medium — create Stamp_Data | +| Legacy stub files in repo | ⚠️ Xcode cleanup needed | High — remove from Xcode manually | +| README accuracy | ⚠️ Several fixes needed | Medium | +| Shopping list vs. training folders | ⚠️ Mismatch | Medium | +| FoilEngine logic | ✅ Sound | Low — document OTA restart requirement | +| CardRecognizer pipeline | ✅ Sound with 2 concerns | Medium — promo filter, edge sampling | +| Heuristic detectors | ✅ Generally good | Low — threshold tuning recommended | +| AppConfig release readiness | ❌ Not release-ready | High — email + IAP IDs must be set |