Compare commits

..

59 Commits

Author SHA1 Message Date
4e36157115 feat: Refine booster pack generation logic for 'The List' cards, Special Guests, and wildcard rarities in both Draft and Play Boosters.
Some checks failed
Build and Deploy / build (push) Failing after 1m11s
2025-12-20 20:03:50 +01:00
139aca6f4f feat: Implement new peasant and standard pack generation algorithms, including special guest support and subset merging, and add relevant documentation. 2025-12-20 19:53:48 +01:00
418e9e4507 feat: Introduce a global confirmation dialog and integrate it for various actions across game rooms, tournament, cube, and deck management, while also adding new UI controls and actions to the game room.
Some checks failed
Build and Deploy / build (push) Failing after 15m40s
2025-12-20 17:21:11 +01:00
eb453fd906 feat: Integrate EDHREC rank into card scoring and refactor auto deck builder for local, more sophisticated bot deck generation. 2025-12-20 16:49:20 +01:00
2794ce71aa feat: integrate AI-powered deck building and card picking using Google Gemini. 2025-12-20 16:18:11 +01:00
664d0e838d feat: add mana curve display component to the deck builder view 2025-12-20 14:54:59 +01:00
a3e45b13ce feat: Implement solo draft mode with bot players and automated deck building. 2025-12-20 14:48:06 +01:00
fd20c3cfb2 refactor: replace window.confirm with a double-click UI confirmation for the clear session button and enhance its styling.
All checks were successful
Build and Deploy / build (push) Successful in 1m38s
2025-12-20 01:51:20 +01:00
412f696646 chore: Update index.html revision in service worker cache manifest. 2025-12-20 01:42:46 +01:00
1853fd9e28 feat: improve card image URL resolution by prioritizing image_uris.normal and falling back to constructed paths. 2025-12-19 03:05:19 +01:00
c9266b9604 cleaned central links 2025-12-19 03:03:45 +01:00
4585e2a944 cleaned devlog 2025-12-19 03:03:15 +01:00
7b47d566c2 feat: Introduce image_uris property to Card interface and update components to prioritize it for card image display. 2025-12-19 02:39:54 +01:00
312530d0f0 feat: Prioritize local card image paths over external URLs for all card displays and interactions. 2025-12-19 02:07:56 +01:00
755ae73d9e fix: remove unused imports and variables from server files to resolve build errors.
All checks were successful
Build and Deploy / build (push) Successful in 1m32s
2025-12-19 01:10:19 +01:00
49080d8233 feat: Refine session clear to preserve UI preferences while resetting game state and standardize image cache paths to full and crop subdirectories.
Some checks failed
Build and Deploy / build (push) Failing after 1m0s
2025-12-18 20:41:01 +01:00
bc5eda5e2a feat: Implement game restart, battlefield styling with art crops and tapped stacks, and initial draw fixes.
Some checks failed
Build and Deploy / build (push) Failing after 1m10s
2025-12-18 20:26:42 +01:00
ca7b5bf7fa feat: Implement core game engine logic, high-velocity UX, and new UI components including radial menu, inspector overlay, and mulligan view. 2025-12-18 18:45:24 +01:00
842beae419 feat: Implement game and server persistence using Redis and file storage, and add a collapsible, resizable card preview sidebar to the game view. 2025-12-18 17:40:36 +01:00
a2a45a995c implemented game server sync 2025-12-18 17:24:07 +01:00
e31323859f fix: Increase ingress and server body size limits to resolve 413 errors and add related documentation.
All checks were successful
Build and Deploy / build (push) Successful in 1m30s
2025-12-18 11:47:10 +01:00
87e38bd0a3 feat: Group pack stack view by type, enhance pack display grid responsiveness, and adjust long-press preview to single-finger with a 500ms delay.
All checks were successful
Build and Deploy / build (push) Successful in 1m26s
2025-12-18 03:47:55 +01:00
6b054ad8fc feat: Consolidate card and land dragging into a single wrapper and manage basic lands directly in the deck. 2025-12-18 03:19:32 +01:00
b39da587d4 feat: Enhance card size slider UI with tooltips and improved layout/styling in draft and deck builder views. 2025-12-18 03:04:41 +01:00
78af33ec99 feat: Add an ALPHA tag to the app title and implement a collapsible card preview sidebar with persistence in draft and deck builder views. 2025-12-18 02:58:48 +01:00
6301e0e7f5 feat: embed card oracle text and type line directly into the draft preview panel with scrollable content. 2025-12-18 02:35:15 +01:00
642e203baf fix: prevent DeckBuilderView content overflow by adding min-w-0 2025-12-18 02:32:31 +01:00
d27cc625e4 feat: Conditionally render dragged card art crop and square aspect ratio for small sizes. 2025-12-18 02:30:20 +01:00
b7e0d1479c feat: enable horizontal scrolling for StackView and use local card width in DeckBuilderView. 2025-12-18 02:27:49 +01:00
bd33f6be24 feat: Persist DeckBuilder UI settings and library height to local storage, and fix sort dropdown positioning. 2025-12-18 02:21:18 +01:00
e6e452b030 feat: Implement localStorage persistence for UI panel resize states in Draft and Deck views. 2025-12-18 02:09:44 +01:00
db601048d9 feat: enhance UI with custom sort dropdown, resizable layouts, StackView DnD, and optimize slider/resize performance with layout fixes. 2025-12-18 02:06:57 +01:00
ebfdfef5ae feat: refactor lobby UI with collapsible panels, add player event notifications, and update card art crop threshold to 130px 2025-12-18 01:38:28 +01:00
851e2aa81d feat: refactor StackView for dynamic grouping and add sorting controls to Deck Builder while reducing card size slider ranges. 2025-12-18 01:30:48 +01:00
0ca29622ef feat: rename Deck to Library and implement tap-to-preview for cards in Deck Builder on touch devices. 2025-12-18 01:26:07 +01:00
d550bc3d04 feat: set default card size and scale values to their minimum in Cube Manager, Draft View, and Deck Builder. 2025-12-18 01:19:11 +01:00
12e60d42f3 feat: Update card preview to use long-press instead of hover on touch devices by improving mobile detection logic. 2025-12-18 01:11:54 +01:00
8995c3f7e8 feat: Add and integrate application favicon to the client.
All checks were successful
Build and Deploy / build (push) Successful in 1m30s
2025-12-18 01:03:00 +01:00
c8d2871126 feat: Implement PWA install prompt with platform-specific handling and dismissal persistence.
All checks were successful
Build and Deploy / build (push) Successful in 1m25s
2025-12-18 00:55:45 +01:00
60db2a91df fixes to left side panel 2025-12-18 00:45:37 +01:00
5bb69c9eb3 style: Adjust height and padding of various UI elements for improved consistency. 2025-12-18 00:38:19 +01:00
7d6ce3995c feat: Introduce custom global context menu for text inputs, refine card touch interactions, and apply global user-select and scrollbar styles. 2025-12-18 00:29:43 +01:00
2bbedfd17f feat: Add PWA support and implement drag-and-drop functionality for deck building.
All checks were successful
Build and Deploy / build (push) Successful in 1m28s
2025-12-17 19:16:55 +01:00
bf40784667 feat: Implement vertical and horizontal layout selection for Draft View and update development documentation.
Some checks failed
Build and Deploy / build (push) Failing after 1m2s
2025-12-17 18:58:17 +01:00
79a44173d0 feat: Implement useCardTouch hook to standardize card interaction and touch event handling across components.
Some checks failed
Build and Deploy / build (push) Failing after 56s
2025-12-17 18:47:48 +01:00
3936260861 feat: Implement 3D flip card preview with foil effects in Draft View and add hover preview control to StackView.
Some checks failed
Build and Deploy / build (push) Failing after 52s
2025-12-17 18:35:57 +01:00
2869c35885 feat: Add numerous Magic: The Gathering card metadata and image files.
Some checks failed
Build and Deploy / build (push) Failing after 50s
2025-12-17 18:12:35 +01:00
da3f7fa137 feat: Implement multiple card display modes (list, grid, stack) in the deck builder and refactor card rendering components for improved interactivity and display options. 2025-12-17 17:31:06 +01:00
845f83086f feat: implement customizable vertical and horizontal deck builder layouts with a new layout switcher and associated rendering refactors. 2025-12-17 17:03:41 +01:00
db785537c9 feat: update deck builder auto-fill to add lands as individual cards for individual management 2025-12-17 16:56:33 +01:00
a0c3b7c59a feat: Update cube box quantity input to use plus/minus buttons and default to 1
All checks were successful
Build and Deploy / build (push) Successful in 1m18s
2025-12-17 16:44:57 +01:00
0b374c7630 refactor: Optimize localStorage by stripping card definitions from packs and lands, and clear available lands state in cube manager. 2025-12-17 16:43:06 +01:00
60c012cbb5 feat: enhance Modal component with children and dynamic sizing, and add box selection for multiple draft boxes in LobbyManager. 2025-12-17 16:36:03 +01:00
0fb330e10b feat: Add 'Test Solo' feature to Cube Manager for randomized deck play, with server support for solo game state on rejoin. 2025-12-17 16:29:12 +01:00
e13aa16766 feat: Implement deck builder magnified card view, land advice, basic land integration, and unlimited time for deck construction. 2025-12-17 16:15:20 +01:00
e5750d9729 fix: increase Socket.IO maxHttpBufferSize to 300MB to support larger drafting payloads and prevent 413 errors. 2025-12-17 15:33:02 +01:00
4ff2eb0ef0 feat: add footer with AI generation attribution to the main application layout.
All checks were successful
Build and Deploy / build (push) Successful in 1m19s
2025-12-17 14:48:49 +01:00
7758b31d6b feat: Implement dynamic pack grid layout using CSS repeat(auto-fill, minmax) for responsive pack display and adjust StackView spacing.
All checks were successful
Build and Deploy / build (push) Successful in 1m24s
2025-12-17 14:44:21 +01:00
90d50bf1c2 feat: Unify card fetching/parsing and pack generation into a single handleGenerate function and button. 2025-12-17 14:37:49 +01:00
159 changed files with 25164 additions and 3823 deletions

View File

@@ -1,45 +0,0 @@
---
trigger: always_on
---
Valid for all generations:
- If foils are not available in the pool, ignore the foil generation
STANDARD GENERATION:
Slots 1-6 (Commons): 6 Common cards. Ensure color balance (attempt to include at least 3 distinct colors).
Slot 7 (Common/List Slot):
- Roll a d100.
- 1-87: 1 Common from Main Set.
- 88-97: 1 Card from "The List" (Common/Uncommon reprint).
- 98-99: 1 Rare/Mythic from "The List".
- 100: 1 Special Guest (High Value).
Slots 8-10 (Uncommons): 3 Uncommon cards.
Slot 11 (Main Rare Slot):
- Roll 1d8.
- If 1-7: Rare.
- If 8: Mythic Rare.
Slot 12 (Land): 1 Basic or Common Dual Land (20% chance of Foil).
Slot 13 (Non-Foil Wildcard):
- Can be any rarity (Common, Uncommon, Rare, Mythic).
- Use weighted probability: ~49% Common, ~24% Uncommon, ~13% Rare, ~13% Mythic (simplified for simulation).
Slot 14 (Foil Wildcard):
- Same rarity weights as Slot 13, but the card must be Foil.
Slot 15 (Marketing): Token or Art Card.
PEASANT GENERATION:
Slots 1-6 (Commons): 6 Common cards. Ensure color balance (attempt to include at least 3 distinct colors).
Slot 7 (Common/List Slot):
- Roll a d100.
- 1-87: 1 Common from Main Set.
- 88-97: 1 Card from "The List" (Common/Uncommon reprint).
- 98-100: 1 Uncommon from "The List".
Slots 8-11 (Uncommons): 4 Uncommon cards.
Slot 12 (Land): 1 Basic or Common Dual Land (20% chance of Foil).
Slot 13 (Non-Foil Wildcard):
- Can be any rarity (Common, Uncommon, Rare, Mythic).
- Use weighted probability: ~49% Common, ~24% Uncommon, ~13% Rare, ~13% Mythic (simplified for simulation).
Slot 14 (Foil Wildcard):
- Same rarity weights as Slot 13, but the card must be Foil.
Slot 15 (Marketing): Token or Art Card.

3
.gitignore vendored
View File

@@ -140,4 +140,5 @@ vite.config.js.timestamp-*
vite.config.ts.timestamp-*
.vite/
src/server/public/cards/*
src/server/public/cards/*
src/server-data

View File

@@ -1,76 +1,7 @@
# Development Status (Central)
## Active Plans
- [Enhance 3D Game View](./devlog/2025-12-14-235500_enhance_3d_game_view.md): Active. Transforming the battlefield into a fully immersive 3D environment.
- [Deck Tester Feature](./devlog/2025-12-15-002500_deck_tester_feature.md): Completed. Implemented a dedicated view to parse custom decks and instantly launch the 3D game sandbox.
- [Game Context Menu & Immersion](./devlog/2025-12-14-235000_game_context_menu.md): Completed. Implemented custom right-click menus and game-feel enhancements.
## Active Tasks
- [x] Enable Clear Session Button (2025-12-20)
## Recent Completions
- [Game Battlefield & Manual Mode](./devlog/2025-12-14-234500_game_battlefield_plan.md): Completed.
- [Helm Chart Config](./devlog/2025-12-14-214500_helm_config.md): Completed.
- [CSV Import Robustness](./devlog/2025-12-16-152253_csv_import_robustness.md): Completed. Enhanced CSV parser to dynamically map columns from headers, supporting custom user imports.
- [Fix Socket Mixed Content](./devlog/2025-12-16-183000_fix_socket_mixed_content.md): Completed. Resolved mixed content error in production by making socket connection URL environment-aware.
- [Draft Rules & Pick Logic](./devlog/2025-12-16-180000_draft_rules_implementation.md): Completed. Enforced 4-player minimum and "Pick 2" rule for 4-player drafts.
- [Fix Pack Duplication](./devlog/2025-12-16-184500_fix_pack_duplication.md): Completed. Enforced deep cloning and unique IDs for all draft packs to prevent opening identical packs.
- [Reconnection & Auto-Pick](./devlog/2025-12-16-191500_reconnection_and_autopick.md): Completed. Implemented session persistence, seamless reconnection, and 30s auto-pick on disconnect.
- [Draft Interface UI Polish](./devlog/2025-12-16-195000_draft_ui_polish.md): Completed. Redesigned the draft view for a cleaner, immersive, game-like experience with no unnecessary scrolls.
- [Resizable Draft Interface](./devlog/2025-12-16-200500_resizable_draft_ui.md): Completed. Implemented user-resizable pool panel and card sizes with persistence.
- [Draft UI Zoom Zone](./devlog/2025-12-16-203000_zoom_zone.md): Completed. Implemented dedicated zoom zone for card preview.
- [Host Disconnect Pause](./devlog/2025-12-16-213500_host_disconnect_pause.md): Completed. Specific logic to pause game when host leaves.
- [2025-12-16-215000_anti_tampering.md](./devlog/2025-12-16-215000_anti_tampering.md): Implemented server-side validation for game actions.
- [2025-12-16-220000_session_persistence.md](./devlog/2025-12-16-220000_session_persistence.md): Plan for session persistence and safer room exit logic.
- [2025-12-16-221000_lobby_improvements.md](./devlog/2025-12-16-221000_lobby_improvements.md): Plan for kick functionality and exit button relocation.
- [Fix Draft UI Layout](./devlog/2025-12-16-215500_fix_draft_ui_layout.md): Completed. Fixed "Waiting for next pack" layout to be consistently full-screen.
- [Draft Timer Enforcement](./devlog/2025-12-16-222500_draft_timer.md): Completed. Implemented server-side 60s timer per pick, AFK auto-pick, and global draft timer loop.
- [Pack Generation Update](./devlog/2025-12-16-224000_pack_generation_update.md): Completed. Implemented new 15-slot Play Booster algorithm with lands, tokens, and wildcards.
- [Card Metadata Enhancement](./devlog/2025-12-16-224500_card_metadata_enhancement.md): Completed. Extended Scryfall fetching and `DraftCard` interfaces to include full metadata (CMC, Oracle Text, etc.).
- [Rich Metadata Expansion](./devlog/2025-12-16-223000_enhance_metadata.md): Completed. Further expanded metadata to include legalities, finishes, artist, frame effects, and produced mana.
- [Persist Metadata](./devlog/2025-12-16-230000_persist_metadata.md): Completed. Implemented IndexedDB persistence for Scryfall metadata to ensure offline availability and reduce API calls.
- [Bulk Parse Feedback](./devlog/2025-12-16-231500_bulk_parse_feedback.md): Completed. Updated `CubeManager` to handle metadata generation properly and provide feedback on missing cards.
- [Full Metadata Passthrough](./devlog/2025-12-16-234500_full_metadata_passthrough.md): Completed. `DraftCard` now includes a `definition` property containing the complete, raw Scryfall object for future-proofing and advanced algorithm usage.
- [Server-Side Caching](./devlog/2025-12-16-235900_server_side_caching.md): Completed. Implemented logic to cache images and metadata on the server upon bulk parsing, and updated client to use local assets.
- [Peasant Algorithm Implementation](./devlog/2025-12-16-225700_peasant_algorithm.md): Completed. Implemented Peasant-specific pack generation rules including slot logic for commons, uncommons, lands, and wildcards.
- [Multi-Expansion Selection](./devlog/2025-12-16-230500_multi_expansion_selection.md): Completed. Implemented searchable multi-select interface for "From Expansion" pack generation, allowing mixed-set drafts.
- [Game Type Filter](./devlog/2025-12-16-231000_game_type_filter.md): Completed. Added Paper/Digital filter to the expansion selection list.
- [Incremental Caching](./devlog/2025-12-16-233000_incremental_caching.md): Completed. Refactored data fetching to cache cards to the server incrementally per set, preventing PayloadTooLarge errors.
- [Server Graceful Shutdown Fix](./devlog/2025-12-17-002000_server_shutdown_fix.md): Completed. Implemented signal handling to ensure clean process exit on Ctrl+C.
- [Cube Sticky Sidebar](./devlog/2025-12-17-003000_cube_sticky_sidebar.md): Completed. Made the Cube Manager left sidebar sticky to improve usability with long pack lists.
- [Cube Full Width Layout](./devlog/2025-12-17-003500_cube_full_width.md): Completed. Updated Cube Manager to use the full screen width.
- [Cube Archidekt View](./devlog/2025-12-17-004500_archidekt_view.md): Completed. Implemented column-based stacked view for packs.
- [Cube Mobile UI Fixes](./devlog/2025-12-17-005000_mobile_ui_fixes.md): Completed. Fixed overlapping elements and disabled hover previews on mobile.
- [Mobile Long-Press Preview](./devlog/2025-12-17-005500_mobile_long_press.md): Completed. Implemented long-press trigger for card magnification on small screens.
- [Mobile Fullscreen Preview](./devlog/2025-12-17-010000_mobile_fullscreen_preview.md): Completed. Updated mobile preview to be a centered fullscreen overlay.
- [Mobile Preview Animations](./devlog/2025-12-17-010500_mobile_preview_animations.md): Completed. Implemented phase-in layout and phase-out animations for mobile preview.
- [Mobile Preview Polish](./devlog/2025-12-17-011000_mobile_preview_polish.md): Completed. Refined mobile enter/exit easing and added premium foil finish.
- [Enhanced Foil Effects](./devlog/2025-12-17-011500_enhanced_foils.md): Completed. implemented a multi-layer holographic sheen for foil cards.
- [Rolling Rainbow Foil](./devlog/2025-12-17-012000_rolling_rainbow_foil.md): Completed. Updated foil effect to feature a scrolling, milder rainbow shimmer.
- [Card Visibility Boost](./devlog/2025-12-17-013000_card_visibility_boost.md): Completed. Added mild white overlay to all card previews for better visibility on dark backgrounds.
- [Optimized Rolling Foil](./devlog/2025-12-17-013500_optimized_rolling_foil.md): Completed. Implemented continuous full-spectrum rainbow foil effect with mild white sheen.
- [Metallic Foil Refinement](./devlog/2025-12-17-014000_metallic_foil_refinement.md): Completed. Adjusted foil to emphasize metallic shimmer/glare over rainbow color saturation.
- [Circular Foil Animation](./devlog/2025-12-17-014500_circular_foil_animation.md): Completed. Replaced linear glare with a rotating gaussian circular sheen.
- [Mild Foil Animation](./devlog/2025-12-17-015000_mild_foil_animation.md): Completed. Tuned down foil brightness and overlay intensity to be milder and consistent with non-foils.
- [Pro Foil Implementation](./devlog/2025-12-17-020000_pro_foil_implementation.md): Completed. Implemented advanced CSS-based holographic texture and animation.
- [Universal Preview Animations](./devlog/2025-12-17-020500_universal_preview_animations.md): Completed. Enabled entrance/exit animations for card previews on all devices.
- [Mobile Touch Interaction](./devlog/2025-12-17-021000_mobile_touch_fix.md): Completed. Updated long-press logic to persist preview during finger movement, closing only on release.
- [Entrance Animation Fix](./devlog/2025-12-17-021500_entrance_animation_fix.md): Completed. Implemented 'isMounted' state to ensuring scale-in animation triggers correctly on first render.
- [Foil Bug Fix](./devlog/2025-12-17-022000_foil_bug_fix.md): Completed. Fixed regression where foil animations applied to non-foil cards on desktop.
- [Universal Foil Application](./devlog/2025-12-17-022500_universal_foil_application.md): Completed. Applied foil animation to Grid View and Stack View card thumbnails.
- [Smart Preview Suppression](./devlog/2025-12-17-023000_smart_preview_suppression.md): Completed. Disabled hover preview for card elements that are already rendered large enough on screen.
- [Compact Card Layout](./devlog/2025-12-17-023500_compact_card_layout.md): Completed. Decreased card sizes in Grid and Stack views for a denser UI.
- [View Scale Slider](./devlog/2025-12-17-024000_view_scale_slider.md): Completed. Added a slider to dynamically adjust card dimensions, synced across Grid and Stack views.
- [Dynamic Art Cropping](./devlog/2025-12-17-024500_dynamic_art_cropping.md): Completed. Implemented automatic switching to full-art/art-crop images when card size is reduced below readability threshold.
- [Refined Preview Suppression](./devlog/2025-12-17-025000_refined_preview_suppression.md): Completed. Adjusted suppression threshold to 200px to better support Stack View's pop-up behavior.
- [Explicit Preview Suppression](./devlog/2025-12-17-025500_explicit_preview_suppression.md): Completed. Implemented strict `preventPreview` prop to enforce suppression logic reliably regardless of card overlap or DOM state.
- [Synchronized Display Boundaries](./devlog/2025-12-17-030000_synchronized_boundaries.md): Completed. Aligned "Art Crop" and "Preview Suppression" thresholds to 200px (50% slider value) for a unified UI behavior.
- [Squared Art Crops](./devlog/2025-12-17-030500_squared_art_crops.md): Completed. Enforced square aspect ratio for art-crop thumbnails to optimize visual density and stacking.
- [Fix Expansion Generation Limit](./devlog/2025-12-17-024500_fix_expansion_generation_limit.md): Completed. Implemented "Unlimited Pool" mode for expansion drafts to allow generating large numbers of packs from singleton set data.
- [Change Default Filter Flags](./devlog/2025-12-17-025500_change_default_flags.md): Completed. Updated client and server defaults for "Ignore Basic Lands", "Ignore Commander Sets", and "Ignore Tokens" to be unchecked (false).
- [Sidebar Max Width](./devlog/2025-12-17-031000_sidebar_max_width.md): Completed. Constrained the left sidebar in Cube Manager to a maximum width of 400px on large screens to improve layout balance.
- [Strict Pack Generation Logic](./devlog/2025-12-17-030600_fix_strict_pack_generation.md): Succeeded. Enforced strict 14-card (Standard) and 13-card (Peasant) limits, removing fallback logic to prevent invalid pack generation.
- [Toast Notification Replacement](./devlog/2025-12-17-022000_replace_alert_with_toast.md): Completed. Replaced invasive alerts with a custom Toast notification system for smoother UX.
- [Enhanced Toast Visibility](./devlog/2025-12-17-023000_enhanced_toast_visibility.md): Completed. Updated toasts to be top-center, animated, and highly visible with premium styling.
- [Unified Toast Design](./devlog/2025-12-17-023500_unified_toast_design.md): Completed. Refined toast aesthetics to match the global dark/slate theme with subtle colored accents.
- [Animated Copy Button](./devlog/2025-12-17-024000_animated_copy_button.md): Completed. Replaced copy toast with an in-place animated tick button for immediate feedback.
- [Play Online Logic](./devlog/2025-12-17-031500_play_online_logic.md): Completed. Implemented strict pack limits (min 12 for 4 players) and visual feedback for the online lobby button.
- [Lobby Rules Tooltip](./devlog/2025-12-17-032000_lobby_rules_tooltip.md): Completed. Added dynamic rules explanation and supported player indicators to the lobby creation screen.
- [Fix Expansion Pack Generation](./devlog/2025-12-17-140000_fix_expansion_generation.md): Completed. Enforced infinite card pool for expansion drafts to ensure correct pack counts and prevent depletion.
## Devlog Index
- [Enable Clear Session](./devlog/2025-12-20-014500_enable_clear_session.md) - Improved UI/UX for session clearing in CubeManager.

View File

@@ -1,33 +0,0 @@
# PROJ001: Initial Project Setup and Logic Refactoring (Node.js Migration)
## Status: COMPLETED
### Achievements
- **Architecture**: Pivoted from .NET to a **Node.js Monolith** structure to natively support real-time state synchronization via Socket.IO.
- **Frontend Infrastructure**: Configured **React** 19 + **Vite** + **Tailwind CSS** (v3) in `src/client`.
- **Backend Infrastructure**: Initialized **Express** server with **Socket.IO** in `src/server` for handling API requests and multiplayer draft state.
- **Refactoring**: Successfully ported legacy `gemini-generated.js` logic into specialized TypeScript services:
- `CardParserService.ts`: Regex-based list parsing.
- `ScryfallService.ts`: Data fetching with caching.
- `PackGeneratorService.ts`: Pack creation logic.
- **UI Implementation**: Developed `CubeManager`, `PackCard`, and `StackView` components.
- **Cleanup**: Removed all .NET artifacts and dependencies.
- **Tooling**: Updated `Makefile` for unified Node.js development commands.
### How to Run
- **Install**: `make install` (or `cd src && npm install`)
- **Run Development**: `make dev` (Runs Server and Client concurrently)
- **Build**: `make build`
### Manual Verification Steps
1. **Run**: `make dev`
2. **Access**: Open `http://localhost:5173` (Client).
3. **Test**:
- Click "Load Demo List" in the Cube Manager.
- Verify cards are fetched from Scryfall.
- Click "Generate Pools".
- Verify packs are generated and visible in Stack/Grid views.
### Next Steps
- Implement `DraftSession` state management in `src/server`.
- Define Socket.IO events for lobby creation and player connection.

View File

@@ -1,29 +0,0 @@
# Migration to Node.js Backend
## Objective
Convert the project from a .NET backend to a Node.js (TypeScript) backend and remove the .NET infrastructure.
## Plan
### Phase 1: Structure Initialization
- [ ] Initialize `src` as a Node.js project (`package.json`, `tsconfig.json`).
- [ ] Create directory structure:
- [ ] `src/server`: Backend logic.
- [ ] `src/client`: Move existing React frontend here.
- [ ] `src/shared`: Shared interfaces/types.
### Phase 2: React Frontend Migration
- [ ] Move `src/MtgDraft.Web/Client` contents to `src/client/src`.
- [ ] Move configuration files (`vite.config.ts`, `tailwind.config.js`, etc.) to `src/client` root or adjust as needed.
- [ ] Ensure frontend builds and runs via Vite (dev server).
### Phase 3: Node.js Backend Implementation
- [ ] Set up Express/Fastify server in `src/server/index.ts`.
- [ ] Configure Socket.IO foundations.
- [ ] Configure build scripts to build client and server.
### Phase 4: Verification
- [ ] Verify application runs with `npm run dev`.
### Phase 5: Cleanup
- [ ] Delete `MtgDraft.*` folders.

View File

@@ -1,30 +0,0 @@
# Implementation of Core Functionalities
## Status
Completed
## Description
Implemented the core functionalities based on the reference `gemini-generated.js` file, refactoring the monolithic logic into a modular architecture.
## Changes
1. **Services**:
- Created `CardParserService` for parsing bulk text lists.
- Created `ScryfallService` for fetching card data with caching and batching.
- Created `PackGeneratorService` for generating booster packs with various rules (Peasant, Standard, Chaos).
2. **Modules**:
- **CubeManager**: Implemented the Draft Preparation Phase UI (Input, Filters, Generation).
- **TournamentManager**: Implemented the Tournament Bracket generation logic and UI.
3. **Components**:
- `PackCard`: card component with List, Grid, and Stack views.
- `StackView`: 3D card stack visualization.
- `TournamentPackView`: "Blind Mode" / Box view for generated packs.
4. **Architecture**:
- Created `App.tsx` as the main shell with Tab navigation (Draft vs Bracket).
- Integrated all components into the main entry point.
## Next Steps
- Integrate Socket.IO for real-time draft synchronization (Multiplayer).
- Implement the "Live Draft" interface.

View File

@@ -1,19 +0,0 @@
# Bug Fix: React Render Error and Pack Generation Stability
## Issue
User reported "root.render(" error visible on page and "Generate Packs" button ineffective.
## Diagnosis
1. **main.tsx**: Found nested `root.render( <StrictMode> root.render(...) )` call. This caused runtime errors and visible artifact text.
2. **CubeManager.tsx**: Service classes (`ScryfallService`, `PackGeneratorService`) were instantiated inside the functional component body without `useMemo`. This caused recreation on every render, leading to cache loss (`ScryfallService` internal cache) and potential state inconsistencies.
3. **Pack Generation**: Double-clicking or rapid state updates caused "phantom" generation runs with empty pools, resetting the packs list to 0 immediately after success.
## Resolution
1. **Fixed main.tsx**: Removed the nested `root.render` call.
2. **Refactored CubeManager.tsx**:
* Memoized all services using `useMemo`.
* Added `loading` state to `generatePacks` to prevent double-submissions.
* Wrapped generation logic in `setTimeout` to allow UI updates and `try/catch` for robustness.
## Status
Verified via browser subagent (logs confirmed 241 packs generated). UI now prevents race conditions.

View File

@@ -1,24 +0,0 @@
# Bug Fix: Card Parser Robustness
## User Request
"The problem is that if the scryfall id is missing, no card is retrieved so no card is generated, instead the system should be able to retrieve cards and generate packs even without scryfall id"
## Diagnosis
The `CardParserService` currently performs basic name extraction. It fails to strip set codes and collector numbers common in export formats (e.g., MTG Arena exports like `1 Shock (M20) 160`).
This causes `ScryfallService` to search for "Shock (M20) 160" as an exact name, which fails. The system relies on successful Scryfall matches to populate the card pool; without matches, the pool is empty, and generation produces 0 packs.
## Implementation Plan
1. **Refactor `CardParserService.ts`**:
* Enhance regex to explicitly handle and strip:
* Parentheses containing text (e.g., `(M20)`).
* Collector numbers at the end of lines.
* Set codes in square brackets if present.
* Maintain support for `Quantity Name` format.
* Ensure exact name cleanup to maximize Scryfall "exact match" hits.
2. **Verification**:
* Create a test input imitating Arena export.
* Verify via browser subagent that cards are fetched and packs are generated.
## Update Central
Update `CENTRAL.md` with this task.

View File

@@ -1,26 +0,0 @@
# Enhancement: Set-Based Pack Generation
## Status: Completed
## Summary
Implemented the ability to fetch entire sets from Scryfall and generate booster boxes.
## Changes
1. **ScryfallService**:
* Added `fetchSets()` to retrieve expansion sets.
* Added `fetchSetCards(setCode)` to retrieve all cards from a set.
2. **PackGeneratorService**:
* Added `generateBoosterBox()` to generate packs without depleting the pool.
* Added `buildTokenizedPack()` for probabilistic generation (R/M + 3U + 10C).
3. **CubeManager UI**:
* Added Toggle for "Custom List" vs "From Expansion".
* Added Set Selection Dropdown.
* Added "Number of Boxes" input.
* Integrated new service methods.
## Usage
1. Select "From Expansion" tab.
2. Choose a set (e.g., "Vintage Masters").
3. Choose number of boxes (default 3).
4. Click "Fetch Set".
5. Click "Generate Packs".

View File

@@ -1,18 +0,0 @@
# Cleanup: Remove Tournament Mode
## Status: Completed
## Summary
Removed the "Tournament Mode" view and "Editor Mode" toggle from the Cube Manager. The user requested a simplified interface that lists packs without grouping them into "Boxes".
## Changes
1. **CubeManager.tsx**:
* Removed `tournamentMode` state and setter.
* Removed usage of `TournamentPackView` component.
* Removed the "Tournament Mode / Editor Mode" toggle button.
* Simplified rendering to always show the pack list (grid/list/stack view) directly.
* Removed unsused `TournamentPackView` import and icon imports.
## Impact
* The UI is now streamlined for the "Host" to just see generated packs.
* The `TournamentPackView` component is no longer used but file remains for now.

View File

@@ -1,18 +0,0 @@
# Enhancement: UI Simplification for Set Generation
## Status: Completed
## Summary
Refined the Cube Manager UI to hide redundant options when generating packs from an entire expansion set.
## Changes
1. **CubeManager.tsx**:
* **Conditional Rendering**: The "Card Source" options (Chaos Draft vs Split by Expansion) are now **hidden** when "From Expansion" mode is selected.
* **Automatic State Handling**:
* Selecting "From Expansion" automatically sets generation mode to `by_set`.
* Selecting "Custom List" resets generation mode to `mixed` (user can still change it).
* **Rationale**: Using an entire set implies preserving its structure (one set), whereas a custom list is often a cube (chaos) or a collection of specific sets where the user might want explicitly mixed packs.
## Impact
* Reduces visual noise for the user when they simply want to draft a specific set.
* Prevents invalid configurations (e.g., selecting "Chaos Draft" for a single set, which technically works but is confusing in context of "Set Generation").

View File

@@ -1,37 +0,0 @@
# Work Plan: Real Game & Online Multiplayer
## User Epics
1. **Lobby System**: Create and join private rooms.
2. **Game Setup**: Use generated packs to start a game.
3. **Multiplayer Draft**: Real-time drafting with friends.
4. **Chat**: In-game communication.
## Tasks
### 1. Backend Implementation (Node.js + Socket.IO)
- [ ] Create `src/server/managers/RoomManager.ts` to handle room state.
- [ ] Implement `Room` and `Player` interfaces.
- [ ] Update `src/server/index.ts` to initialize `RoomManager` and handle socket events:
- `create_room`
- `join_room`
- `leave_room`
- `send_message`
- `start_game` (placeholder for next phase)
### 2. Frontend Implementation (React)
- [ ] Create `src/client/src/modules/lobby` directory.
- [ ] Create `LobbyManager.tsx` (The main view for finding/creating rooms).
- [ ] Create `GameRoom.tsx` (The specific room view with chat and player list).
- [ ] Create `socket.ts` service in `src/client/src/services` for client-side socket handling.
- [ ] Update `App.tsx` to include the "Lobby" tab.
- [ ] Update `CubeManager.tsx` to add "Create Online Room" button.
### 3. Integration
- [ ] Ensure created room receives the packs from `CubeManager`.
- [ ] Verify players can join via Room ID.
- [ ] Verify chat works.
## Technical Notes
- Use `socket.io-client` on frontend.
- Generate Room IDs (short random strings).
- Manage state synchronization for the room (players list updates).

View File

@@ -1,15 +0,0 @@
# Fix UUID Error in Insecure Contexts
## Problem
The user reported a `TypeError: crypto.randomUUID is not a function` when accessing the application from a public IP. This is because `crypto.randomUUID()` is part of the Web Crypto API, which is often restricted to secure contexts (HTTPS) or localhost. When accessing via `http://PUBLIC_IP:PORT`, the browser disables this API.
## Solution
We need to implement a fallback UUID generation method that works in non-secure contexts.
## Plan
1. Modify `src/client/src/services/PackGeneratorService.ts`.
2. Add a private method `generateUUID()` to the `PackGeneratorService` class (or a standalone helper function in the module) that:
* Checks if `crypto.randomUUID` is available.
* If yes, uses it.
* If no, uses a fallback algorithm (e.g., `Math.random()` based v4 UUID generation).
3. Replace the call `crypto.randomUUID()` with this new method.

View File

@@ -1,31 +0,0 @@
# Game Interactions Implementation
## Objective
Implement basic player interactions for the MTG game, including library, battlefield, and other game mechanics.
## Changes
1. **Backend (`src/server/managers/GameManager.ts`)**:
* Created `GameManager` class to handle game state.
* Defined `GameState`, `PlayerState`, `CardInstance` interfaces.
* Implemented `createGame`, `handleAction` (move, tap, draw, life).
* Integrated with `socket.io` handlers in `server/index.ts`.
2. **Frontend (`src/client/src/modules/game`)**:
* Created `GameView.tsx`: Main game board with drag-and-drop zones (Hand, Battlefield, Library, Graveyard).
* Created `CardComponent.tsx`: Draggable card UI with tap state.
* Updated `GameRoom.tsx`: Added game state handling and "Start Game (Test)" functionality.
3. **Socket Service**:
* Identify `start_game` and `game_action` events.
* Listen for `game_update` to sync state.
## Status
- Basic sandbox gameplay is operational.
- Players can move cards between zones freely (DnD).
- Tap/Untap and Life counters implemented.
- Test deck (Mountain/Bolt) provided for quick testing.
## Next Steps
- Implement actual rules enforcement (Stack, Priority).
- Implement Deck Builder / Draft Integration (load actual drafted decks).
- Improve UI/UX (animations, better card layout).

View File

@@ -1,41 +0,0 @@
# Draft & Deck Building Phase
## Objective
Implement the "Draft Phase" (Pack Passing) and "Deck Building Phase" (Pool + Lands) logic and UI, bridging the gap between Lobby and Game.
## Changes
1. **Backend - Draft Logic (`src/server/managers/DraftManager.ts`)**:
* Implemented `DraftManager` class.
* Handles pack distribution (3 packs per player).
* Implements `pickCard` logic with queue-based passing (Left-Right-Left).
* Manages pack rounds (Wait for everyone to finish Pack 1 before opening Pack 2).
* Transitions to `deck_building` status upon completion.
2. **Server Integration (`src/server/index.ts`)**:
* Added handlers for `start_draft` and `pick_card`.
* Broadcasts `draft_update` events.
3. **Frontend - Draft UI (`src/client/src/modules/draft/DraftView.tsx`)**:
* Displays active booster pack.
* Timer (visual only for now).
* Click-to-pick interaction.
* Preview of drafted pool.
4. **Frontend - Deck Builder UI (`src/client/src/modules/draft/DeckBuilderView.tsx`)**:
* **Split View**: Card Pool vs. Current Deck.
* **Drag/Click**: Click card to move between pool and deck.
* **Land Station**: Add basic lands (Plains, Island, Swamp, Mountain, Forest) with unlimited supply.
* **Submit**: Sends deck to server (via `player_ready` - *Note: Server integration for deck storage pending final game start logic*).
5. **Integration (`GameRoom.tsx`)**:
* Added routing based on room status: `waiting` -> `drafting` -> `deck_building` -> `game`.
* Added "Start Real Draft" button to lobby.
## Status
- **Drafting**: Fully functional loop. Players pick cards, pass packs, and proceed through 3 rounds.
- **Deck Building**: UI is ready. Players can filter, build, and add lands.
- **Next**: Need to finalize the "All players ready" logic in `deck_building` to trigger the actual `start_game` using the submitted decks. Currently, submitting triggers a placeholder event.
## To Verify
- Check passing direction (Left/Right).
- Verify Basic Land addition works correctly in the final deck object.

View File

@@ -1,37 +0,0 @@
# Image Caching Implementation
## Objective
Implement a robust image caching system that downloads card images to the server when creating a draft room, ensuring all players can see images reliably via local serving.
## Changes
1. **Backend - Image Service (`src/server/services/CardService.ts`)**:
* Created `CardService` class.
* Implements `cacheImages` which downloads images from external URLs to `src/server/public/cards`.
* Uses a concurrency limit (5) to avoid rate limiting.
* Checks for existence before downloading to avoid redundant work.
2. **Backend - Server Setup (`src/server/index.ts`)**:
* Enabled static file serving for `/cards` endpoint mapping to `src/server/public/cards`.
* Added `POST /api/cards/cache` endpoint that accepts a list of cards and triggers cache logic.
* Increased JSON body limit to 50mb to handle large set payloads.
3. **Frontend - Lobby Manager (`LobbyManager.tsx`)**:
* Updated `handleCreateRoom` workflow.
* **Pre-Creation**: Extracts all unique cards from generated packs.
* **Cache Request**: Sends list to `/api/cards/cache`.
* **Transformation**: Updates local pack data to point `image` property to the local server URL (`/cards/{scryfallId}.jpg`) instead of remote Scryfall URL.
* This ensures that when `create_room` is emitted, the room state on the server (and thus all connected clients) contains valid local URLs.
4. **Fixes**:
* Addressed `GameRoom.tsx` crash by replacing `require` with dynamic imports (or static if preloaded) and fixing clipboard access.
* Fixed TS imports in server index.
## Status
- **Image Caching**: Functional. Creating a room now triggers a download process on the terminal.
- **Local Serving**: Cards should now load instantly from the server for all peers.
## How to Verify
1. Generate packs in Draft Management.
2. Create a Room. Watch server logs for "Cached image: ..." messages.
3. Join room.
4. Start Draft. Images should appear.

View File

@@ -1,17 +0,0 @@
# Fix Draft Card Images
## Issue
Users reported that images were not showing in the Draft Card Selection UI.
## Root Causes
1. **Missing Proxy**: The application was attempting to load cached images from `http://localhost:5173/cards/...`. Vite Dev Server (port 5173) was not configured to proxy these requests to the backend (port 3000), resulting in 404 errors for all local images.
2. **Incorrect Property Access**: `DraftView.tsx` (and `DeckBuilderView.tsx`) attempted to access `card.image_uris.normal`. However, the `DraftCard` object generated by `PackGeneratorService` and modified by `LobbyManager` stores the image URL in `card.image`. This property was being ignored.
## Fixes
1. **Vite Config**: Added a proxy rule for `/cards` in `src/vite.config.ts` to forward requests to `http://localhost:3000`.
2. **Frontend Views**: Updated `DraftView.tsx` and `DeckBuilderView.tsx` to prioritize `card.image` when rendering card images.
## Verification
- Start the draft.
- Images should now load correctly from the local cache (or fallback if configured).
- Inspect network tab to verify images are loaded from `/cards/...` with a 200 OK status.

View File

@@ -1,28 +0,0 @@
# Fix Submit Deck Button
## Issue
Users reported that "Submit Deck" button was not working.
## Root Causes
1. **Missing Event Handler**: The server was not listening for the `player_ready` event emitted by the client.
2. **Incomplete Payload**: The client was sending `{ roomId, deck }` but the server needed `playerId` to identify who was ready, which was missing from the payload.
3. **Missing State Logic**: The `RoomManager` did not have a concept of "Ready" state or "Playing" status, meaning the transition from Deck Building to Game was not fully implemented.
## Fixes
1. **Client (`DeckBuilderView.tsx`)**: Updated `player_ready` emission to include `playerId`.
2. **Server (`RoomManager.ts`)**:
- Added `ready` and `deck` properties to `Player` interface.
- Added `playing` to `Room` status.
- Implemented `setPlayerReady` method.
3. **Server (`index.ts`)**:
- Implemented `player_ready` socket handler.
- Added logic to check if *all* active players are ready.
- If all ready, automatically transitions room status to `playing` and initializes the game using `GameManager`, loading the submitted decks.
- ensured deck loading uses cached images (`card.image`) if available.
## Verification
1. Draft cards.
2. Build deck.
3. Click "Submit Deck".
4. Server logs should show "All players ready...".
5. Client should automatically switch to `GameView` (Battlefield).

View File

@@ -1,22 +0,0 @@
# Fix Hooks Violation and Implement Waiting State
## Issue
1. **React Hook Error**: Users encountered "Rendered fewer hooks than expected" when the game started. This was caused by conditional returns in `GameRoom.tsx` appearing *before* hook declarations (`useState`, `useEffect`).
2. **UX Issue**: Players who submitted their decks remained in the Deck Builder view, able to modify their decks, instead of seeing a waiting screen.
## Fixes
1. **Refactored `GameRoom.tsx`**:
- Moved all `useState` and `useEffect` hooks to the top level of the component, ensuring they are always called regardless of the render logic.
- Encapsulated the view switching logic into a helper function `renderContent()`, which is called inside the main return statement.
2. **Implemented Waiting Screen**:
- Inside `renderContent`, checking if the room is in `deck_building` status AND if the current player has `ready: true`.
- If ready, displays a "Deck Submitted" screen with a list of other players and their readiness status.
- Updated the sidebar player list to show a "• Ready" indicator.
## Verification
1. Start a draft with multiple users (or simulate it).
2. Complete draft and enter deck building.
3. Submit deck as one player.
4. Verify that the view changes to "Deck Submitted" / Waiting screen.
5. Submit deck as the final player.
6. Verify that the game starts automatically for everyone without crashing (React Error).

View File

@@ -1,32 +0,0 @@
# Game Battlefield & Manual Mode Implementation Plan
## Goal
Implement a 3D-style battlefield and manual game logic for the MTG Draft Maker. The system should allow players to drag and drop cards freely onto the battlefield, tap cards, and manage zones (Hand, Library, Graveyard, Exile) in a manual fashion typical of virtual tabletops.
## Status: Completed
## Implemented Features
- **3D Battlefield UI**:
- Used CSS `perspective: 1000px` and `rotateX` to create a depth effect.
- Cards are absolutely positioned on the battlefield based on percentage coordinates (0-100%).
- Shadows and gradients enhance the "tabletop" feel.
- **Manual Game Logic**:
- **Free Drag and Drop**: Players can move cards anywhere on the battlefield. Coordinates are calculated relative to the drop target.
- **Z-Index Management**: Backend tracks a `maxZ` counter. Every move or flip brings the card to the front (`z-index` increment).
- **Actions**:
- **Tap/Untap**: Click to toggle (rotate 90 degrees).
- **Flip**: Right-click to toggle face-up/face-down status.
- **Draw**: Click library to draw.
- **Life**: Buttons to increment/decrement life.
- **Multiplayer Synchronization**:
- All actions (`MOVE_CARD`, `TAP_CARD`, `FLIP_CARD`, `UPDATE_LIFE`) are broadcast via Socket.IO.
- Opponent's battlefield is rendered in a mirrored 3D perspective.
## Files Modified
- `src/client/src/modules/game/GameView.tsx`: Main UI logic.
- `src/client/src/modules/game/CardComponent.tsx`: Added context menu support.
- `src/server/managers/GameManager.ts`: Logic for actions and state management.
## Next Steps
- Test with real players to fine-tune the "feel" of dragging (maybe add grid snapping option later).
- Implement "Search Library" feature (currently just Draw).

View File

@@ -1,39 +0,0 @@
# Game Context Menu & Immersion Update Plan
## Goal
Implement a robust, video-game-style context menu for the battlefield and cards. This menu will allow players to perform advanced manual actions required for MTG, such as creating tokens and managing counters, while eliminating "browser-like" feel.
## Status: Completed
## Implemented Features
- **Custom Game Context Menu**:
- Replaces default browser context menu.
- Dark, video-game themed UI with glassmorphism.
- Animated entrance (fade/zoom).
- **Functionality**:
- **Global (Background)**:
- "Create Token" (Default 1/1, 2/2, Treasure).
- **Card Specific**:
- "Tap / Untap"
- "Flip Face Up / Down"
- "Add Counter" (Submenu: +1/+1, -1/-1, Loyalty)
- "Clone (Copy)" (Creates an exact token copy of the card)
- "Delete Object" (Removing tokens or cards)
- **Backend Logic**:
- `GameManager` now handles:
- `ADD_COUNTER`: Adds/removes counters logic.
- `CREATE_TOKEN`: Generates new token instances with specific stats/art.
- `DELETE_CARD`: Removes objects from the game.
- **Frontend Integration**:
- `GameView` manages menu state (position, target).
- `CardComponent` triggers menu only on itself, bubbling prevented.
- Hand cards also support right-click menus.
## Files Modified
- `src/client/src/modules/game/GameContextMenu.tsx`: New component.
- `src/client/src/modules/game/GameView.tsx`: Integrated menu.
- `src/server/managers/GameManager.ts`: Added token/counter handlers.
## Next Steps
- Add sounds for menu open/click.
- Add more token types or a token editor.

View File

@@ -1,41 +0,0 @@
# Enhancement Plan: True 3D Game Area
The goal is to transform the game area into a "really 3D game" experience using CSS 3D transforms.
## Objectives
1. **Immersive 3D Table**: Create a convincing 3D perspective of a table where cards are placed.
2. **Card Physics Simulation**: Visuals should simulate cards having weight, thickness, and position in 3D space.
3. **Dynamic Camera/View**: Fix the viewing angle to be consistent with a player sitting at a table.
## Implementation Steps
### 1. Scene Setup (GameView.tsx)
- Create a "Scene" container with high `perspective` (e.g., `1200px` to `2000px`).
- Create a "World" container that holds the table and other elements, allowing for global rotation if needed.
- Implement a "TableSurface" div that is rotated `rotateX(40-60deg)` to simulate a flat surface viewed from an angle.
### 2. Battlefield Enchancement
- The player's battlefield should be the bottom half of the table.
- The opponent's battlefield should be the top half.
- Use `transform-style: preserve-3d` extensively.
- Add a grid/mat texture to the table surface to enhance the depth perception.
### 3. Card 3D Component (CardComponent.tsx)
- Refactor `CardComponent` to use a 3D structure.
- Add a container for 3D positioning (`translate3d`).
- Add a visual "lift" when dragging or hovering (`translateZ`).
- Enhance the shadow to be on the "table" surface, separating from the card when lifting.
- *Implementation Note*: The shadow might need to be a separate element `after` the card or a separate div to stay on the table plane while the card lifts.
### 4. Lighting and Atmosphere
- Add a "Light Source" effect (radial gradient overlay).
- Adjust colors to be darker/moodier, fitting the "Dark Gaming UI" aesthetic.
## Tech Stack
- CSS via Tailwind + Inline Styles for dynamic coordinates.
- React for state/rendering.
## Execution Order
1. Refactor `GameView.tsx` layout to standard CSS 3D Scene structure.
2. Update `CardComponent.tsx` to handle 3D props (tilt, lift).
3. Fine-tune values for perspective and rotation.

View File

@@ -1,31 +0,0 @@
# Docker Containerization and Build Fixes
## Objectives
- Create a Dockerfile to package the application as a monolith (Node.js + React).
- Fix TypeScript build errors preventing successful compilation.
- Verify the build process.
## Changes
- **Dockerfile**: Created multi-stage build using `node:20-alpine`.
- Installs dependencies.
- Builds frontend.
- Prunes dev dependencies.
- **Server Entry (`src/server/index.ts`)**: Added logic to serve static `dist` files and handle client-side routing in production.
- **Package.json**: Moved `tsx` to dependencies and updated `start` script.
- **Code Fixes**: Removed unused variables in client and server code used to satisfy strict TypeScript rules:
- `DeckBuilderView.tsx`: Removed unused `payload`.
- `DraftView.tsx`: Removed unused `CardComponent`.
- `GameView.tsx`: Removed unused `myCommand`, `oppGraveyard`.
- `DraftManager.ts`: Removed unused `numPlayers`, `cardIndex`.
- `GameManager.ts`: Renamed unused args in `shuffleLibrary`.
- **Helm Chart**: Created a complete Helm chart configuration in `helm/mtg-draft-maker`:
- `Chart.yaml`: Defined chart metadata.
- `values.yaml`: Configured defaults (Image `git.commandware.com/services/mtg-online-drafter:main`, Port 3000).
- `templates/`: Added Deployment, Service, Ingress, and ServiceAccount manifests.
- **Persistence**: Added configuration to mount a Persistent Volume Claim (PVC) at `/app/server/public/cards` for storing cached images. Disabled by default.
- Linted successfully.
## Status
- Docker build successful (`docker build -t mtg-draft-maker .`).
- Helm chart created and linted.
- Ready for K8s deployment.

View File

@@ -1,32 +0,0 @@
# Deck Tester Feature Implementation
## Objective
Create a way to add a cards list to generate a deck and directly enter the game ui to test the imported deck, using the same exact game and battlefield of the draft.
## Implementation Details
### Frontend
1. **DeckTester Component (`src/client/src/modules/tester/DeckTester.tsx`)**:
- Created a new component that allows users to input a deck list (text area or file upload).
- Reused `CardParserService` and `ScryfallService` to parse the list and fetch card data.
- Implemented image caching logic (sending to `/api/cards/cache`).
- Connects to socket and emits `start_solo_test`.
- Upon success, switches view to `GameRoom` with the received `room` and `game` state.
2. **App Integration (`src/client/src/App.tsx`)**:
- Added a new "Deck Tester" tab to the main navigation.
- Uses the `Play` icon from lucide-react.
3. **GameRoom Enhancement (`src/client/src/modules/lobby/GameRoom.tsx`)**:
- Added `initialGameState` prop to allow initializing the `GameView` immediately without waiting for a socket update (handling potential race conditions or state sync delays).
### Backend
1. **Socket Event (`src/server/index.ts`)**:
- Added `start_solo_test` event handler.
- Creates a room with status `playing`.
- Initializes a game instance.
- Adds cards from the provided deck list to the game (library zone).
- Emits `room_update` and `game_update` to the client.
## Outcome
The user can now navigate to "Deck Tester", paste a deck list, and immediately enter the 3D Game View to test interactions on the battlefield. This reuses the entire Draft Game infrastructure, ensuring consistency.

View File

@@ -1,6 +0,0 @@
Implemented CSV export for generated packs and cards.
Implemented CSV copy to clipboard functionality.
Implemented CSV import template download.
Removed demo button and functionality from CubeManager.
Updated CSV import template content.
Refactored parsing logic to support complex CSV imports.

View File

@@ -1,21 +0,0 @@
# CSV Import Robustness Update
## Background
The user provided a specific CSV format associated with typical automated imports. The requirement was to extract relevant information (Quantity, Name, Finish, Scryfall ID) while ignoring other fields (such as Condition, Date Added, etc.).
## Changes
- Refactored `src/client/src/services/CardParserService.ts` to implement dynamic header parsing.
- The `parse` method now:
- Detects if the first line is a CSV header containing "Quantity" and "Name".
- Maps columns to indices based on the header.
- Specifically looks for `Quantity`, `Name`, `Finish`, and `Scryfall ID` (checking common variations like 'scryfall_id', 'id', 'uuid').
- Uses strictly mapped columns if a header is detected, ensuring other fields are ignored as requested.
- Falls back gracefully to previous generic parsing logic if no matching header is found, preserving backward compatibility with Arena/MTGO exports and simple lists.
## Verification
- Verified manually via a test script that the provided CSV content parses correctly into the `CardIdentifier` memory structure.
- The extraction correctly identifies Quantity, Name, Finish (Normal/Foil), and Scryfall UUID.
## Next Steps
- Ensure the frontend `CubeManager` works seamlessly with this update (no changes needed there as it uses the service).

View File

@@ -1,17 +0,0 @@
# 2025-12-16 - Draft Rules and Logic Implementation
## Draft Minimum Players
- Added backend check in `index.ts` to prevent drafting with fewer than 4 players.
- Emit `draft_error` to room if condition is not met.
- Added `draft_error` listener in `GameRoom.tsx` to notify users.
## 4-Player Draft Rules (Pick 2)
- Modified `DraftManager.ts`:
- Added `pickedInCurrentStep` to track picks within a single pack pass cycle.
- Implemented logic in `pickCard`:
- If 4 players: Require 2 picks before passing pack.
- Else: Require 1 pick.
- Logic handles pack exhaustion (if pack runs out before picks completed, it passes).
## Robustness
- Updated `rejoin_room` handler in `index.ts` to send the current `draft` state if the room is in `drafting` status. This allows users to refresh and stay in the draft flow (critical for multi-pick scenarios).

View File

@@ -1,14 +0,0 @@
# Fix Socket Mixed Content Error
## Objective
Resolve the "Mixed Content" error preventing the Online Lobby and Deck Tester from functioning in the production Kubernetes environment. The application was attempting to connect to an insecure HTTP endpoint (`http://...:3000`) from a secure HTTPS page.
## Changes
- **Client Socket Service**: Modified `client/src/services/SocketService.ts` to make the connection URL environment-aware.
- In **Production**: The URL is now `undefined`, allowing Socket.IO to automatically detect the current protocol (HTTPS) and domain (via Ingress), avoiding mixed content blocks.
- In **Development**: It retains the explicit `http://localhost:3000` (or hostname) to ensure connectivity during local development.
- **TypeScript Config**: Added a reference directive `/// <reference types="vite/client" />` to `SocketService.ts` to ensure `import.meta.env` is correctly typed during the build.
## Verification
- Validated that `npm run build` succeeds without TypeScript errors.
- Confirmed that the fix aligns with standard Vite + Socket.IO production deployment patterns.

View File

@@ -1,13 +0,0 @@
# 2025-12-16 - Fix Pack Duplication in Draft
## Problem
Users reported behavior consistent with "opening the same pack twice". This occurs when the pack objects distributed to players share the same memory reference. If the input source (e.g., from Frontend Generator) contains duplicate references (e.g., created via `Array.fill(pack)`), picking a card from "one" pack would seemingly remove it from "another" pack in a future round, or valid packs would re-appear.
## Solution
- Modified `DraftManager.createDraft` to enforce Strict Isolation of pack instances.
- Implemented **Deep Cloning**: Even if the input array contains shared references, we now map over `allPacks`, spreading the pack object and mapping the cards array to new objects.
- **Unique IDs**: Re-assigned a unique internal ID to every single pack (format: `draft-pack-{index}-{random}`) to guarantee that every pack in the system is distinct, regardless of the quality of the input data.
## Impact
- Ensures that every "pack" opened in the draft is an independent entity.
- Prevents state leakage between rounds or players.

View File

@@ -1,21 +0,0 @@
# 2025-12-16 - Reconnection and Auto-Pick
## Reconnection Logic
- Use `localStorage.setItem('active_room_id', roomId)` in `LobbyManager` to persist connection state.
- Upon page load, if a saved room ID exists, attempted to automatically reconnect via `rejoin_room` socket event.
- Updated `socket.on('join_room')` and `rejoin_room` on the server to update the player's socket ID mapping, canceling any pending "disconnect" timers.
## Disconnection Handling
- Updated `RoomManager` to track `socketId` and `isOffline` status for each player.
- In `index.ts`, `socket.on('disconnect')`:
- Marks player as offline.
- Starts a **30-second timer**.
- If timer expires (user did not reconnect):
- Triggers `draftManager.autoPick(roomId, playerId)`.
- `autoPick` selects a random card from the active pack to unblock the draft flow.
## Auto-Pick Implementation
- Added `autoPick` to `DraftManager`:
- Checks if player has an active pack.
- Selects random index.
- Calls `pickCard` internally to process the pick (add to pool, pass pack, etc.).

View File

@@ -1,23 +0,0 @@
# Draft Interface UI Polish
## Status
- [x] Analyze current UI issues (bottom border, scrolling).
- [x] Remove global padding from `App.tsx`.
- [x] Refactor `DraftView.tsx` for a cleaner, game-like experience.
- [x] Implement immersive 3D effects and tray-style pool view.
## Context
The user requested to improve the draft card pick interface. Specifically to remove the ugly bottom border, avoid page scrolls, and make it feel more like a game.
## Implementation Details
### `src/client/src/App.tsx`
- Removed `pb-20` from the main container to allow full-screen layouts without forced scrolling at the bottom.
### `src/client/src/modules/draft/DraftView.tsx`
- **Layout**: Changed to relative positioning with `overflow-hidden` to contain all elements within the viewport.
- **Visuals**:
- Added a radial gradient background overlay.
- Redesigned the "Current Pack" area with `[perspective:1000px]` and 3D hover transforms.
- Redesigned the "Your Pool" bottom area to be a "tray" with `backdrop-blur`, gradient background, and removed the boxy border.
- **Scrollbars**: Hidden scrollbars in the main pack view for a cleaner look (`[&::-webkit-scrollbar]:hidden`).

View File

@@ -1,34 +0,0 @@
# Resizable Draft Interface
## Status
- [x] Implement resizable bottom "Pool" panel.
- [x] Implement resizable card size slider.
- [x] Persist settings to `localStorage`.
## Technical Plan
### `src/client/src/modules/draft/DraftView.tsx`
1. **State Initialization**:
- `poolHeight`: number (default ~220). Load from `localStorage.getItem('draft_poolHeight')`.
- `cardScale`: number (default 1 or specific width like 224px). Load from `localStorage.getItem('draft_cardScale')`.
2. **Resize Handle**:
- Insert a `div` cursor-row-resize between the Main Area and the Bottom Area.
- Implement `onMouseDown` handler to start dragging.
- Implement `onMouseMove` and `onMouseUp` on the window/document to handle the resize logic.
3. **Card Size Control**:
- Add a slider (`<input type="range" />`) in the Top Header area to adjust `cardScale`.
- Apply this scale to the card images/containers in the Main Area.
4. **Persistence**:
- `useEffect` hooks to save state changes to `localStorage`.
5. **Refactoring Styling**:
- Change `h-[220px]` class on the bottom panel to `style={{ height: poolHeight }}`.
- Update card width class `w-56` to dynamic style or class based on scale.
## UX Improvements
- Add limit constraints (min height for pool, max height for pool).
- Add limit constraints for card size (min visible, max huge).

View File

@@ -1,13 +0,0 @@
# Card Zoom on Hover
## Status
- [x] Add `hoveredCard` state to `DraftView`.
- [x] Implement `onMouseEnter`/`onMouseLeave` handlers for cards in both Pick and Pool areas.
- [x] rendering a fixed, high z-index preview of the hovered card.
- [x] Disable right-click context menu on Draft interface.
## Implementation Details
- **File**: `src/client/src/modules/draft/DraftView.tsx`
- **Zoom Component**: A fixed `div` containing the large card image.
- **Position**: Fixed to the left or right side of the screen (e.g., `left-10 top-1/2 -translate-y-1/2`) to avoid covering the grid being interacted with (which is usually centered).
- **Styling**: Large size (e.g., `w-80` or `h-[500px]`), shadow, border, rounded corners.

View File

@@ -1,15 +0,0 @@
# Card Zoom on Hover - Dedicated Zone
## Status
- [x] Add `hoveredCard` state to `DraftView` (Already done).
- [x] Implement `onMouseEnter`/`onMouseLeave` handlers (Already done).
- [x] Refactor `DraftView` layout to include a dedicated sidebar for card preview.
- [x] Move the zoomed card image into this dedicated zone instead of a fixed overlay.
## Implementation Details
- **File**: `src/client/src/modules/draft/DraftView.tsx`
- **Layout Change**:
- Wrap the central card selection area in a `flex-row` container.
- Add a Left Sidebar (e.g., `w-80`) reserved for the zoomed card.
- Ensure the main card grid takes up the remaining space (`flex-1`).
- **Behavior**: When no card is hovered, the sidebar can show a placeholder or remain empty/decorative.

View File

@@ -1,22 +0,0 @@
# Host Disconnect Pause Logic
## Objective
Ensure the game pauses for all players when the Host disconnects, preventing auto-pick logic from advancing the game state. enable players to leave cleanly.
## Changes
1. **Server (`src/server/index.ts`)**:
* Refactored socket handlers.
* Implemented `startAutoPickTimer` / `stopAllRoomTimers` helpers.
* Updated `disconnect` handler: Checks if disconnected player is passed host. If true, pauses game (stops all timers).
* Updated `join_room` / `rejoin_room`: Resumes game (restarts timers) if Host reconnects.
* Added `leave_room` event handler to properly remove players from room state.
2. **Frontend (`src/client/src/modules/lobby/LobbyManager.tsx`)**:
* Updated `handleExitRoom` to emit `leave_room` event, preventing "ghost" connections.
3. **Frontend (`src/client/src/modules/lobby/GameRoom.tsx`)**:
* Fixed build error (unused variable `setGameState`) by adding `game_update` listener.
* Verified "Game Paused" overlay logic exists and works with the new server state (`isHostOffline`).
## Result
Host disconnection now effectively pauses the draft flow. Reconnection resumes it. Players can leave safely.

View File

@@ -1,26 +0,0 @@
# Anti-Tampering Implementation
## Objective
Implement a robust anti-tampering system to prevent players (including the host) from manipulating the game state via malicious client-side emissions.
## Changes
1. **Server (`src/server/managers/RoomManager.ts`)**:
* Added `getPlayerBySocket(socketId)` to securely identify the player associated with a connection, eliminating reliance on client-provided IDs.
2. **Server (`src/server/index.ts`)**:
* Refactored all major socket event listeners (`pick_card`, `game_action`, `start_draft`, `player_ready`) to use `roomManager.getPlayerBySocket(socket.id)`.
* The server now ignores `playerId` and `roomId` sent in the payload (where applicable) and uses the trusted session context instead.
* This ensures that a user can only perform actions for *themselves* in the room they are *actually connected to*.
3. **Server (`src/server/managers/GameManager.ts`)**:
* Updated `handleAction` to accept an authentic `actorId`.
* Added ownership/controller checks to sensitive actions:
* `moveCard`: Only the controller can move a card.
* `updateLife`: Only the player can update their own life.
* `drawCard`, `createToken`, etc.: Validated against `actorId`.
4. **Frontend (`GameView.tsx`, `DraftView.tsx`, `DeckBuilderView.tsx`)**:
* Cleaned up socket emissions to stop sending redundant `roomId` and `playerId` fields, aligning client behavior with the new secure server expectations (though server would safely ignore them anyway).
## Result
The system is now significantly more resistant to session hijacking or spoofing. Users cannot act as other players or manipulate game state objects they do not control, even if they manually emit socket events from the console.

View File

@@ -1,12 +0,0 @@
# Fix Draft UI Layout Consistency
## Objective
Fix the layout inconsistency where the "Waiting for next pack..." screen and other views in the Draft interface do not fully occupy the screen width, causing the UI to look collapsed or disconnected from the global sidebars.
## Changes
1. **DraftView.tsx**: Added `flex-1` and `w-full` to the root container. This ensures the component expands to fill the available space in the `GameRoom` flex container, maintaining the full-screen layout even when content (like the "waiting" message) is minimal.
2. **DeckBuilderView.tsx**: Added `flex-1` and `w-full` to the root container for consistency and to ensure the deck builder also behaves correctly within the main layout.
## Verification
- The `DraftView` should now stretch to fill the area between the left edge (or internal Zoom sidebar) and the right Lobby/Chat sidebar in `GameRoom`.
- The "Waiting for next pack..." message will remain centered within this full-height, full-width area, with the background gradient covering the entire zone.

View File

@@ -1,38 +0,0 @@
# implementation_plan - Draft Session Persistence and Restoration
This plan addresses the issue where users are unable to reliably rejoin a draft session as a player after reloading or exiting, often re-entering as a spectator. It ensures robust session synchronization to local storage and handles player "leave" actions safely during active games.
## User Objectives
- **Session Restoring**: Automatically rejoin the correct session and player seat upon reloading the application.
- **Prevent Accidental Data Loss**: Ensure "Exiting" a room during an active draft does not destroy the player's seat, allowing them to rejoin.
- **Start New Draft**: Maintain the ability for a user to explicitly invalid/abandon an old session to start a new one (handled by creating a new room, which overwrites local storage).
## Proposed Changes
### 1. Server-Side: Safer `leaveRoom` Logic
**File**: `src/server/managers/RoomManager.ts`
- Modify `leaveRoom` method.
- **Logic**:
- If `room.status` is `'waiting'`, remove the player (current behavior).
- If `room.status` is `'drafting'`, `'deck_building'`, or `'playing'`, **DO NOT** remove the player from `room.players`. Instead, mark them as `isOffline = true` (similar to a disconnect).
- This ensures that if the user rejoins with the same `playerId`, they find their existing seat instead of being assigned a new "spectator" role.
### 2. Server-Side: Robust `rejoin_room` Handler
**File**: `src/server/index.ts`
- Update `socket.on('rejoin_room')`.
- **Change**: Implement an acknowledgement `callback` pattern consistent with other socket events.
- **Logic**:
- Accept `{ roomId, playerId }`.
- If successful, invoke `callback({ success: true, room, draftState })`.
- Broadcast `room_update` to other players (to show user is back online).
### 3. Client-Side: Correct Rejoin Implementation
**File**: `src/client/src/modules/lobby/LobbyManager.tsx`
- **Fix**: In the `rejoin_room` emit call, explicitly include the `playerId`.
- **Enhancement**: Utilize the callback from the server to confirm reconnection before setting state.
- **Exit Handling**: The `handleExitRoom` function clears `localStorage`, which is correct for an explicit "Exit". However, thanks to the server-side change, if the user manually rejoins the same room code, they will reclaim their seat effectively.
## Verification Plan
1. **Test Reload**: Start a draft, refresh the browser. Verify user auto-rejoins as Player.
2. **Test Exit & Rejoin**: Start a draft, click "Exit Room". Re-enter the Room ID manually. Verify user rejoins as Player (not Spectator).
3. **Test New Draft**: Create a room, start draft. Open new tab (or exit), create NEW room. Verify new room works and old session doesn't interfere.

View File

@@ -1,46 +0,0 @@
# implementation_plan - Lobby Improvements and Kick Functionality
This plan addresses user feedback regarding the draft resumption experience, exit button placement, and host management controls.
## User Objectives
1. **Resume Draft on Re-entry**: Ensure that manually joining a room (after exiting) correctly restores the draft view if a draft is in progress.
2. **Exit Button Placement**: Move the "Exit Room" button to be near the player's name in the lobby sidebar.
3. **Kick Player**: Allow the Host to kick players from the room.
## Proposed Changes
### 1. Server-Side: Kick Functionality
**File**: `src/server/managers/RoomManager.ts`
- **Method**: `kickPlayer(roomId, playerId)`
- **Logic**:
- Remove the player from `room.players`.
- If the game is active (drafting/playing), this is a destructive action. We will assume for now it removes them completely (or marks offline? "Kick" usually implies removal).
- *Decision*: If kicked, they are removed. If the game breaks, that's the host's responsibility.
**File**: `src/server/index.ts`
- **Event**: `kick_player`
- **Logic**:
- Verify requester is Host.
- Call `roomManager.kickPlayer`.
- Broadcast `room_update`.
- Emit `kicked` event to the target socket (to force them to client-side exit).
### 2. Client-Side: Re-entry Logic Fix
**File**: `src/client/src/modules/lobby/GameRoom.tsx`
- **Logic**: Ensure `GameRoom` correctly initializes or updates `draftState` when receiving new props.
- Add a `useEffect` to update local `draftState` if `initialDraftState` prop changes (though `key` change on component might be better, we'll use `useEffect`).
### 3. Client-Side: UI Updates
**File**: `src/client/src/modules/lobby/GameRoom.tsx`
- **Sidebar**:
- Update the player list rendering.
- If `p.id === currentPlayerId`, show an **Exit/LogOut** button next to the name.
- If `isMeHost` and `p.id !== me`, show a **Kick/Ban** button next to the name.
- **Handlers**:
- `handleKick(targetId)`: Warning confirmation -> Emit `kick_player`.
- `handleExit()`: Trigger the existing `onExit`.
## Verification Plan
1. **Test Kick**: Host kicks a player. Player should be removed from list and client should revert to lobby (via socket event).
2. **Test Exit**: Click new Exit button in sidebar. Should leave room.
3. **Test Re-join**: Join the room code again. Should immediately load the Draft View (not the Lobby View).

View File

@@ -1,32 +0,0 @@
# 2025-12-16 - Draft Timer Enforcement
## Status
Completed
## Description
Implemented server-side timer enforcement for the draft phase to ensure the game progresses even if players are AFK or disconnected.
## Changes
1. **Server: DraftManager.ts**
* Updated `DraftState` to include `pickExpiresAt` (timestamp) for each player and `isPaused` for the draft.
* Initialize `pickExpiresAt` to 60 seconds from now when a player receives a pack (initial or passed).
* Implemented `checkTimers()` method to iterate over all active drafts and players. If `Date.now() > pickExpiresAt`, it triggers `autoPick`.
* Implemented `setPaused()` to handle host disconnects. When resuming, timers are reset to 60s to prevent immediate timeout.
2. **Server: index.ts**
* Removed ad-hoc `playerTimers` map and individual `setTimeout` logic associated with socket disconnect events.
* Added a global `setInterval` (1 second tick) that calls `draftManager.checkTimers()` and broadcasts updates.
* Updated `disconnect` handler to pause the draft if the host disconnects (`draftManager.setPaused(..., true)`).
* Updated `join_room` / `rejoin_room` handlers to resume the draft if the host reconnects.
3. **Client: DraftView.tsx**
* Updated the timer display logic to calculate remaining time based on `draftState.players[id].pickExpiresAt` - `Date.now()`.
* The timer now accurately reflects the server-enforced deadline.
## Behavior
* **Drafting**: Each pick has a 60-second limit.
* **Deck Building**: 120-second limit. If time runs out, the game forces start. Any unready players have their entire draft pool submitted as their deck automatically.
* **Timeout**: If time runs out, a random card is automatically picked, and the next pack (if available) is loaded with a fresh 60s timer.
* **AFK**: If a user is AFK, the system continues to auto-pick for them until the draft concludes.
* **Host Disconnect**: If the host leaves, the draft pauses for everyone. Timer stops.
* **Host Reconnect**: Draft resumes, and all active pick timers are reset to 60s.

View File

@@ -1,21 +0,0 @@
# Plan: Enhance Card Metadata
## Objective
Update Scryfall fetching and parsing logic to include comprehensive metadata for cards. This will enable more precise pack generation algorithms in the future (e.g., filtering by legality, format, artist, or specific frame effects).
## Steps
1. **Update `ScryfallCard` Interface (`src/client/src/services/ScryfallService.ts`)**
* Add fields for `legalities`, `finishes`, `games`, `produced_mana`, `artist`, `released_at`, `frame_effects`, `security_stamp`, `promo_types`.
* Define a more robust `ScryfallCardFace` interface.
2. **Update `DraftCard` Interface (`src/client/src/services/PackGeneratorService.ts`)**
* Add corresponding fields to the internal `DraftCard` interface to store this data in the application state.
3. **Update `PackGeneratorService.processCards`**
* Map the new fields from `ScryfallCard` to `DraftCard` during the processing phase.
* Ensure `cardFaces` are also mapped correctly if present (useful for Flip cards where we might want front/back info).
4. **Verification**
* Build the project to ensure no type errors.
* (Optional) Run a test script or verify in browser if possible, but static analysis should suffice for interface updates.

View File

@@ -1,30 +0,0 @@
# Pack Generation Algorithm Update
## Objective
Update the pack generation logic to match a new 15-slot "Play Booster" structure.
The new structure includes:
- **Slots 1-6:** Commons (Color Balanced).
- **Slot 7:** Common (87%), List (C/U 10%, R/M 2%), or Special Guest (1%).
- **Slots 8-10:** Uncommons (3).
- **Slot 11:** Rare (7/8) or Mythic (1/8).
- **Slot 12:** Basic Land or Common Dual Land (20% Foil).
- **Slot 13:** Wildcard (Non-Foil) - Weighted Rarity.
- **Slot 14:** Wildcard (Foil) - Weighted Rarity.
- **Slot 15:** Marketing Token / Art Card.
## Implementation Details
1. **Updated `PackGeneratorService.ts`**:
- Modified `processedPools` to explicitly categorize `lands` (Basic + Common Dual) and `tokens`.
- Updated `processCards` to sort cards into these new pools (instead of filtering them out completely).
- Rewrote `buildSinglePack` (for `standard` rarity mode) to implement the 15-slot sequencing.
- Implemented logic for:
- Color balancing commons (naive attempt).
- "The List" simulation (using Wildcard logic from pools).
- Slots 13/14 Wildcards with weighted probabilities.
- Foil application (cloning card and setting `finish`).
- Slot 12 Land selection (preferring separate land pool).
- Added interfaces for `typeLine` and `layout` to `DraftCard`.
## Status
- Implemented and Verified via static check (TS linting was fixed).
- Ready for testing in the client.

View File

@@ -1,26 +0,0 @@
# Card Metadata Enhancement
## Objective
Enhance the Scryfall data fetching and internal card representation to include full metadata (CMC, Oracle Text, Power/Toughness, Collector Number, etc.). This allows strictly precise pack generation and potential future features like mana curve analysis or specific slot targeting.
## Changes
1. **Updated `ScryfallService.ts`**:
- Extended `ScryfallCard` interface to include:
- `cmc` (number)
- `mana_cost` (string)
- `oracle_text` (string)
- `power`, `toughness` (strings)
- `collector_number` (string)
- `color_identity` (string[])
- `keywords` (string[])
- `booster` (boolean)
- `promo`, `reprint` (booleans)
- Verified that `fetch` calls already return this data; TS interface update exposes it.
2. **Updated `PackGeneratorService.ts`**:
- Extended `DraftCard` internal interface to include the same metadata fields (normalized names like `manaCost`, `oracleText`).
- Updated `processCards` function to map these fields from the Scryfall response to the `DraftCard` object.
## Impact
- Pack generation now has access to rich metadata.
- Future-proofs the system for "The List" exact matching (via collector number or promo types) and game logic (CMC sorting).

View File

@@ -1,20 +0,0 @@
# Peasant Algorithm Implementation
## Overview
Implemented the detailed "Peasant" pack generation algorithm in `PackGeneratorService.ts`.
## Changes
- Updated `buildSinglePack` in `PackGeneratorService.ts` to include specific logic for Peasant rarity mode.
- Implemented slot-based generation:
- Slots 1-6: Commons (Color Balanced)
- Slot 7: Common or "The List" (Simulated)
- Slots 8-11: Uncommons
- Slot 12: Land (20% Foil)
- Slot 13: Non-Foil Wildcard (Weighted by rarity)
- Slot 14: Foil Wildcard (Weighted by rarity)
- Slot 15: Marketing Token
## Notes
- Used existing helper methods `drawColorBalanced` and `drawUniqueCards`.
- Simulated "The List" logic using available Common/Uncommon pools as exact "The List" metadata might not be available in standard pools provided to the generator.
- Wildcard weights follow the specification (~49% C, ~24% U, ~13% R, ~13% M).

View File

@@ -1,28 +0,0 @@
# Plan: Persist Scryfall Metadata
## Objective
Persist fetched Scryfall card metadata in the browser's IndexedDB. This ensures that:
1. Metadata (including the newly added rich fields) is saved across sessions.
2. Pack generation can rely on this data without re-fetching.
3. The application works better offline or with poor connection after initial fetch.
## Implementation Steps
1. **Create `src/client/src/utils/db.ts`**
* Implement a lightweight IndexedDB wrapper.
* Database Name: `mtg-draft-maker`
* Store Name: `cards`
* Methods: `putCard`, `getCard`, `getAllCards`, `bulkPut`.
2. **Update `ScryfallService.ts`**
* Import the DB utilities.
* In `constructor` or a new `initialize()` method, load all persisted cards into memory (`cacheById` and `cacheByName`).
* In `fetchCollection`, `fetchSetCards`, etc., whenever cards are fetched from API, save them to DB via `bulkPut`.
* Modify `fetchCollection` to check memory cache (which is now pre-filled from DB) before network.
3. **Refactor `fetchCollection` deduplication**
* Since cache is pre-filled, the existing check `if (this.cacheById.has(...))` will effectively check the persisted data.
## Verification
* Reload page -> Check if cards are loaded immediately without network requests (network tab).
* Check Application -> Storage -> IndexedDB in browser devtools (mental check).

View File

@@ -1,14 +0,0 @@
# Multi-Expansion Selection
## Objective
Enhanced the "From Expansion" pack generation feature in the Cube Manager to allow users to select multiple expansions and use a searchable interface.
## Implementation Details
1. **Searchable Interface**: Replaced the simple set dropdown with a dedicated set selection UI featuring a search input for fuzzy filtering by set name or code.
2. **Multi-Select Capability**: Users can now check multiple sets from the filtered list.
3. **Frontend State Refactor**: Migrated `selectedSet` (string) to `selectedSets` (string array) in `CubeManager.tsx`.
4. **Fetch Logic Update**: Updated `fetchAndParse` to iterate through all selected sets, fetching card data for each sequentially and combining the results into the parse pool.
5. **Generation Logic**: The existing `generateBoosterBox` logic now naturally consumes the combined pool of cards from multiple sets, effectively allowing for "Chaos Drafts" or custom mixed-set environments based on the user's selection.
## Status
Completed. The Cube Manager UI now supports advanced set selection scenarios.

View File

@@ -1,15 +0,0 @@
# Game Type Filter for Expansion Selection
## Objective
Add a filter to the "From Expansion" set selection to easily distinguish between Paper and Digital (MTGA/MTGO) sets.
## Implementation Details
1. **ScryfallService Update**: Updated `ScryfallSet` interface to include the `digital` boolean property and mapped it in `fetchSets`.
2. **CubeManager UI**: Added a toggle filter bar above the set list with three options:
* **All**: Shows all sets.
* **Paper**: Shows only sets where `digital` is false.
* **Digital**: Shows only sets where `digital` is true.
3. **Filter Logic**: Integrated the game type filter into the existing search filter logic in `CubeManager`.
## Status
Completed. Users can now filter the expansion list by game type.

View File

@@ -1,20 +0,0 @@
# Plan: Improve Parse Bulk Feedback
## Objective
Enhance the "Parse Bulk" workflow in `CubeManager` to provide explicit feedback on the result of the Scryfall metadata fetching. This ensures the user knows that "images and metadata" have been successfully generated (fetched) for their list, fulfilling the request for precision.
## Steps
1. **Update `CubeManager.tsx`**
* In `fetchAndParse` function:
* Track `notFoundCount` (identifiers that returned no Scryfall data).
* Track `successCount` (identifiers that were successfully enriched).
* After the loop, check if `notFoundCount > 0`.
* Show a summary notification/alert: "Processed X cards. Y cards could not be identified."
* (Optional) If many failures, maybe show a list of names? For now, just the count is a good start.
2. **Verify Data Integrity**
* Ensure that the `processedData` uses the fully enriched `DraftCard` objects (which we know it does from previous steps).
## Why This Matters
The user asked to "Generate image and metadata... upon Parse bulk". While the backend/service logic is done, the UI needs to confirm this action took place to give the user confidence that the underlying algorithm now has the precise data it needs.

View File

@@ -1,13 +0,0 @@
# Incremental Data Caching
## Objective
Enable caching of card data to the server incrementally per set when multiple sets are selected, rather than sending a single massive payload at the end. avoiding `PayloadTooLargeError`.
## Implementation Details
1. **Helper Function**: Created `cacheCardsToServer` helper within `fetchAndParse` to handle server communication for a chunk of cards.
2. **Incremental Loop**: Modified the set fetching loop to call `cacheCardsToServer` immediately after receiving data for each set.
3. **UI Feedback**: Updated progress text to clearly indicate when the system is "Caching [Set Name]..." to the server.
4. **Error Handling**: Added try/catch within the caching helper to prevent a single cache failure from aborting the entire fetch process (logs error to console).
## Status
Completed. Large multi-set fetches should now be robust against body size limits.

View File

@@ -1,20 +0,0 @@
# Plan: Full Metadata Passthrough
## Objective
Ensure that the `DraftCard` objects used throughout the application (and eventually sent to the backend) contain the **complete** original metadata from Scryfall. The user has explicitly requested access to "all cards informations" for future algorithms.
## Steps
1. **Update `ScryfallService.ts`**
* Add an index signature `[key: string]: any;` to the `ScryfallCard` interface. This acknowledges that the object contains more fields than strictly typed, preventing TypeScript from complaining when accessing obscure fields, and correctly modeling the API response.
2. **Update `PackGeneratorService.ts`**
* Add `sourceData: ScryfallCard;` (or similar name like `scryfallData`) to the `DraftCard` interface.
* In `processCards`, assign the incoming `cardData` (the full Scryfall object) to this new property.
## Impact
* **Data Size**: Payload size for rooms will increase, but this is acceptable (and requested) for the richness of data required.
* **Flexibility**: Future updates to pack generation (e.g., checking specific `frame_effects` or `prices`) will not require interface updates; the data will already be there in `card.sourceData`.
## Verification
* The valid "Parse Bulk" operation will now produce `DraftCard`s that, if inspected, contain the full Scryfall JSON.

View File

@@ -1,25 +0,0 @@
# Plan: Server-Side Caching of Bulk Data
## Objective
Implement server-side caching of both card images and metadata upon bulk parsing, ensuring the application relies on local assets rather than external Scryfall URLs.
## Implementation Steps
1. **Refactor Server Architecture (`CardService.ts`)**
* Update storage paths to `public/cards/images` (previously `public/cards`) and `public/cards/metadata`.
* Implement `cacheMetadata` to save JSON files alongside images.
2. **Update API Endpoint (`index.ts`)**
* Modify `POST /api/cards/cache` to handle metadata saving in addition to image downloading.
* Update static file serving to map `/cards` to `public/cards`, making images accessible at `/cards/images/{id}.jpg`.
3. **Update Client Logic (`CubeManager.tsx`, `PackGeneratorService.ts`, `LobbyManager.tsx`)**
* **Generation**: Pass a flag (`useLocalImages`) to the generator service.
* **Url Construction**: Generator now produces URLs like `${origin}/cards/images/{id}.jpg` when the flag is set.
* **Triggers**: `CubeManager` immediately sends parsed data to the server for caching before generating packs.
* **Consistency**: `LobbyManager` updated to look for images in the new `/cards/images` path for multiplayer sessions.
## Impact
* **Performance**: Initial "Parse Bulk" takes slightly longer (due to server cache call), but subsequent interactions are instant and local.
* **Reliability**: Application works offline or without Scryfall after initial parse.
* **Precision**: Metadata is now persisted as individual JSONs on the backend, ready for future complex backend algorithms.

View File

@@ -1,17 +0,0 @@
# Server Graceful Shutdown Fix
## Context
The user reported that the application process was not exiting clean (hanging for >5s) after pressing Ctrl+C. This indicated active handles (like intervals or open sockets) were preventing the Node.js process from terminating effectively.
## Changes
Modified `src/server/index.ts` to implement a proper graceful shutdown mechanism:
1. **Interval Management**: Captured the global draft timer `setInterval` ID into a variable `draftInterval`.
2. **Shutdown Handler**: Created a `gracefulShutdown` function that:
- Clears the `draftInterval`.
- Closes the Socket.IO server (`io.close()`).
- Closes the HTTP server (`httpServer.close()`), waiting for existing connections to close, then exits with code 0.
- Sets a 10-second timeout to force exit with code 1 if connections don't close in time.
3. **Signal Listeners**: Attached `gracefulShutdown` to `SIGINT` and `SIGTERM` events.
## Impact
The server should now exit immediately and cleanly when stopped via the terminal, ensuring no zombie processes or port conflicts during development restarts.

View File

@@ -1,14 +0,0 @@
# Cube Manager Sticky Sidebar
## Objective
Update the `CubeManager` layout to make the left-side settings/controls panel sticky. This allows the user to access controls (Generate, Reset, etc.) while scrolling through a long list of generated packs on the right.
## Changes
- Modified `src/client/src/modules/cube/CubeManager.tsx`:
- Added `sticky top-4` to the left column wrapper.
- Added `self-start` to ensure the sticky element doesn't stretch to the full height of the container (which would negate stickiness).
- Added `max-h-[calc(100vh-2rem)]` and `overflow-y-auto` to the left panel to ensure its content remains accessible if it exceeds the viewport height.
- Added `custom-scrollbar` styling for consistent aesthetics.
## Result
The left panel now follows the user's scroll position, improving usability for large pack generations.

View File

@@ -1,12 +0,0 @@
# Cube Manager Full Width Layout
## Objective
Update the `CubeManager` layout to utilize the full width of the screen, removing the maximum width constraint. This allows for better utilization of screen real estate, especially on wider monitors, and provides more space for the pack grid.
## Changes
- Modified `src/client/src/modules/cube/CubeManager.tsx`:
- Removed `max-w-7xl` and `mx-auto` classes from the main container.
- Added `w-full` to ensure the container spans the entire available width.
## Result
The Cube Manager interface now stretches to fill the viewport width, providing a more expansive view for managing packs and settings.

View File

@@ -1,16 +0,0 @@
# Cube Manager Archidekt View
## Objective
Implement an "Archidekt-style" stacked view for pack generation. This view organizes cards into columns by type (Creature, Instant, Land, etc.) with vertical overlapping to save space while keeping headers visible.
## Changes
1. **Refactor PackCard**: Extracted `FloatingPreview` and `CardHoverWrapper` into `src/client/src/components/CardPreview.tsx` to resolve circular dependencies and clean up `PackCard.tsx`.
2. **Update StackView**:
- Rewrite `StackView.tsx` to group cards by `typeLine` (categories: Creature, Planeswalker, Instant, Sorcery, Enchantment, Artifact, Land, Battle, Other).
- Sort cards within categories by CMC.
- Render columns using Flexbox.
- Implement overlapping "card strip" look using negative `margin-bottom` on cards.
- Value tuning: `margin-bottom: -125%` seems appropriate for a standard card aspect ratio to reveal the title bar.
## Result
The "Stack" view option in Cube Manager now renders packs as organized, sorted columns similar to deck-builder interfaces.

View File

@@ -1,20 +0,0 @@
# Cube Manager Mobile Improvements
## Objective
Fix usability issues on mobile devices where UI elements were overlapping and "unusable".
## Changes
1. **Sidebar Responsiveness**:
- Modified `CubeManager.tsx` to apply `sticky` positioning to the left sidebar *only* on large screens (`lg:` prefix). On mobile, it is now standard static flow.
- Limited `max-height` and `overflow-y-auto` only to `lg:` screens.
2. **Header Improvements**:
- Updated the "Packs" sticky header in `CubeManager.tsx` to handle wrapping gracefully.
- Added `backdrop-blur-xl` and slightly higher opacity to ensure content behind it doesn't bleed through visually (fixing "overlap" perception).
- Enabled `overflow-x-auto` for the buttons container to prevent them from breaking out of the viewport on very narrow screens.
3. **Disable Heavy Hovers**:
- Modified `CardPreview.tsx` to disable the `FloatingPreview` (large full-card hover) on devices with width < 1024px. This prevents the preview from sticking or covering the UI on touch devices.
## Result
The UI should now be clean and usable on mobile, with no overlapping elements and a natural scroll flow.

View File

@@ -1,15 +0,0 @@
# Mobile Long-Press Card Preview
## Objective
Enhance mobile usability by allowing users to view a magnified card preview upon long-pressing (500ms) a card, instead of hover (which is disabled on mobile).
## Changes
- Modified `src/client/src/components/CardPreview.tsx`:
- Updated `CardHoverWrapper` to include `touchstart`, `touchend`, and `touchmove` handlers.
- Implemented a 500ms timer on touch start.
- Added logic to cancel the long-press if the user drags/scrolls more than 10 pixels.
- Added `onContextMenu` handler to prevent the default browser menu when a long-press triggers the preview.
- Updated render condition to show preview if `isHovering` (desktop) OR `isLongPressing` (mobile).
## Result
On mobile devices, users can now press and hold on a card to see the full-size preview. Lifting the finger or scrolling hides the preview.

View File

@@ -1,16 +0,0 @@
# Mobile Fullscreen Preview
## Objective
Update the mobile card preview mechanism to display a centered, fullscreen overlay upon long-press, rather than a floating element following the touch point. This provides a clearer view of the card on small screens.
## Changes
- Modified `src/client/src/components/CardPreview.tsx`:
- Updated `FloatingPreview` interface to accept `isMobile: boolean`.
- Added conditional rendering in `FloatingPreview`:
- If `isMobile` is true, it renders a `fixed inset-0` overlay with a centered image, `backdrop-blur`, and entrance animations (`zoom-in` + `fade-in`).
- If false (desktop), it retains the original cursor-following behavior.
- Updated `CardHoverWrapper` to pass the `isMobile` state down to the preview component.
- The preview automatically disappears (unmounts) when the long-press is released, effectively creating a "fade out/close" interaction (visually, the instant close is standard; entrance is animated).
## Result
Long-pressing a card on mobile now brings up a high-quality, centered view of the card that dims the background, improving readability and usability.

View File

@@ -1,18 +0,0 @@
# Mobile Preview Animations
## Objective
Implement smooth "Phase In" and "Phase Out" animations for the mobile fullscreen card preview to replace the instant appear/disappear behavior.
## Changes
- Modified `src/client/src/components/CardPreview.tsx`:
- Updated `CardHoverWrapper` to handle component unmounting with a delay (300ms) when the preview should be hidden on mobile.
- Passed a new `isClosing` prop to `FloatingPreview` during this delay period.
- In `FloatingPreview` (Mobile View):
- Added `transition-all duration-300` base classes.
- Used conditional classes:
- Entrance: `animate-in fade-in zoom-in-95`
- Exit: `animate-out fade-out zoom-out-95` (triggered when `isClosing` is true).
- Fixed syntax errors introduced in previous steps (removed spaces in class names).
## Result
On mobile, the card preview now fades and zooms in smoothly when long-pressed, and fades/zooms out smoothly when released.

View File

@@ -1,21 +0,0 @@
# Mobile Preview Enhancements
## Objective
Enhance the mobile card preview with sophisticated entrance/exit animations and a premium foil effect.
## Changes
- **Refined Animations**:
- **Entering**: Uses `scale-100 opacity-100 ease-out` to simulate the card smoothly arriving into view.
- **Exiting**: Uses `scale-95 opacity-0 ease-in` to simulate the card receding and fading away.
- The transition duration is set to 300ms for a fluid feel.
- **Foil Overlay**:
- Added a multi-layered foil effect for cards with `isFoil=true`.
- **Layer 1**: A moving pulse gradient (`bg-gradient-to-tr` with `via-white/20`) that simulates light catching the surface.
- **Layer 2**: A static color-dodge gradient (`bg-gradient-to-br` with purple/pink/blue) to give the characteristic holographic tint.
- **Effect Implementation**:
- The `FloatingPreview` component now orchestrates these classes based on the `isClosing` prop passed from the wrapper.
## Result
The mobile experience now feels premium, with cards gracefully popping in and out, and foils displaying a distinctive animated sheen.

View File

@@ -1,15 +0,0 @@
# Enhanced Foil Effects
## Objective
Make the foil effect on cards "more visible and cooler" by introducing a multi-layered holographic overlay.
## Changes
- Modified `src/client/src/components/CardPreview.tsx`:
- Created a consistent `FoilOverlay` component used by both Mobile and Desktop previews.
- **Layer 1 (Base Holo)**: Swapped previous subtle gradients for a vibrant `amber-300` / `fuchsia-400` / `cyan-400` gradient with `mix-blend-color-dodge`. Increased opacity to `100` (blended mode handles the transparency feel).
- **Layer 2 (Shimmer)**: Added a diagonal white pulse (`animate-pulse`) with `mix-blend-overlay` to simulate catching the light.
- **Layer 3 (Depth)**: Added a top-down `white-to-black` gradient with `mix-blend-soft-light` to simulate metallic curvature/surface depth.
- Fixed linting errors from previous edits (syntax issues with spaces in class strings).
## Result
Foil cards now possess a distinct, colorful, and metallic sheen that animates, making them stand out significantly more than standard cards.

View File

@@ -1,15 +0,0 @@
# Rolling Rainbow Foil Effect
## Objective
Implement a "milder but more colorful" foil effect with a "rolling rainbow" animation and a mild white overlay, consistent across mobile and desktop.
## Changes
- **CSS Animation**: Added `@keyframes bg-roll` and `.animate-bg-roll` utility in `main.css` to create a continuous background position scrolling effect.
- **Enhanced Foil Overlay**: Updated `FoilOverlay` in `CardPreview.tsx`:
- **Layer 1 (Rolling Rainbow)**: Uses a wide `gradient-to-r` spanning red -> blue -> red (`200% width`). It uses `animate-bg-roll` to scroll horizontally, simulating the color shifting of a foil card as it moves.
- **Layer 2 (Light Glint)**: Retained a subtle diagonal `white/30` pulse (`mix-blend-overlay`) for dynamic lighting.
- **Layer 3 (White Sheen)**: Added a static `white/10` overlay (`mix-blend-soft-light`) to provide the requested "mild white overlay" for a glossy finish.
- **Lint Fix**: Cast `card.finish` to string to resolve TypeScript type overlap errors.
## Result
Foil cards now exhibit a smooth, colorful, rolling rainbow reflection that looks premium and dynamic without being overly chaotic.

View File

@@ -1,13 +0,0 @@
# General Card Visibility Boost
## Objective
Add a mild white overlay to all magnified card previews (both mobile and desktop) to improve visibility against dark backgrounds, as requested.
## Changes
- Modified `src/client/src/components/CardPreview.tsx`:
- Inserted a `<div className="absolute inset-0 bg-white/10 pointer-events-none mix-blend-overlay" />` into the `FloatingPreview` component.
- This overlay is applied to **every** card, regardless of finish (Foil/Normal) or device type.
- It sits immediately on top of the image but below the Foil effects, ensuring it brightens the base art without washing out the holographic details.
## Result
All card previews now have slightly lifted blacks and increased brightness, making them "pop" more against the dark UI backdrops.

View File

@@ -1,13 +0,0 @@
# Optimized Rolling Rainbow Foil
## Objective
Update the foil effect to use a "continuous rainbow" and a "milder white background" as specifically requested.
## Changes
- Modified `FoilOverlay` in `src/client/src/components/CardPreview.tsx`:
- **Continuous Rainbow**: Updated the gradient to encompass the full spectrum (`red` -> `yellow` -> `green` -> `blue` -> `purple` -> `red`) over a linear gradient. This seamless loop ensures the rolling animation (`animate-bg-roll`) is smooth and continuously colorful.
- **Milder White Background**: Removed the heavy soft-light and pulse layers. Replaced them with a very subtle `white/5` overlay using `mix-blend-overlay`. This brightens the foil slightly without washing out the colors.
- **Color Dodge**: Applied `mix-blend-color-dodge` to the container to ensure the rainbow colors interact vibrantly with the underlying card art.
## Result
Foil cards now feature a smooth, full-spectrum rainbow scrolling effect that feels high-quality and "magical," with a balanced brightness level.

View File

@@ -1,13 +0,0 @@
# Metallic Foil Refinement
## Objective
Adjust the foil effect to prioritize "visible shimmer" over "color tinting," preventing the effect from washing out the card's original colors.
## Changes
- Modified `FoilOverlay` in `src/client/src/components/CardPreview.tsx`:
- **Reduced Saturation**: Lowered the opacity of the rolling rainbow layer from `60` down to `30`. This keeps the dynamic color shift but makes it much more subtle, preventing it from overpowering the artwork.
- **Increased Shimmer**: Added a strong `via-white/40` diagonal glare layer with `mix-blend-overlay` and `opacity-80`. This adds a bright, metallic "pop" that moves (`animate-pulse`) across the card, simulating high-gloss reflection.
- **Screen Gloss**: Changed the top finish layer to `mix-blend-screen` with `white/5`. This adds a neutral brightness that lifts the metallic look without shifting the hue.
## Result
The foil effect now looks like a highly reflective metallic surface (the "effect" is visible) rather than a colored filter, preserving the integrity of the original card art.

View File

@@ -1,17 +0,0 @@
# Circular Foil Animation
## Objective
Replace the linear "pulsing" glare with a "gaussian circular animation" to provide a smoother, rotating metallic sheen.
## Changes
- **CSS Animation**: Added `.animate-spin-slow` in `main.css` to rotate elements over an 8-second loop.
- **Foil Component** (`src/client/src/components/CardPreview.tsx`):
- Removed the pulsing linear gradient.
- Added a **rotating radial gradient**:
- Positioned with `absolute inset-[-50%]` to create a canvas larger than the card.
- Uses a white radial gradient (`rgba(255,255,255,0.5) 0% -> transparent 60%`) centered on this larger canvas.
- The `animate-spin-slow` class rotates this entire large gradient layer around the center of the card.
- This creates an effect where a soft "spotlight" or "sheen" continually drifts across the card surface in a circular pattern, simulating light moving over a holographic texture.
## Result
The foil glare is now a soft, rotating circular highlight, giving a distinctly different and more sophisticated "gaussian" light play compared to the previous linear pulse.

View File

@@ -1,16 +0,0 @@
# Mild Foil Animation
## Objective
Reduce the intensity of foil effects to make the static appearance identical to non-foil cards (as requested), while keeping the animation "mildly visible" rather than dominating.
## Changes
- Modified `FoilOverlay` in `src/client/src/components/CardPreview.tsx`:
- **Removed Static Gloss**: Deleted the `bg-white/5 mix-blend-screen` layer. This ensures the base brightness of foil cards matches the standard "Universal Gloss" shared with non-foils.
- **Softened Circular Glare**:
- Reduced the white intensity in the radial gradient from `0.5` to `0.25`.
- Reduced the layer opacity from `80` to `25`.
- This makes the rotating white sheen subtle and ghostly rather than a bright spotlight.
- *Retained*: The low-opacity rolling rainbow layer (`opacity-30`) to provide the necessary color play.
## Result
Foil cards now look cleaner and less washed out, matching the visual weight of normal cards, but possess a delicate, rotating shimmer that catches the eye without distracting from the art.

View File

@@ -1,20 +0,0 @@
# Pro Foil Implementation
## Objective
Implement a high-fidelity "Pro" foil effect using generic CSS techniques inspired by community "Holo" styles, creating a sophisticated rainbow and texture mapping.
## Changes
- **CSS Class `foil-holo`**:
- Added to `src/client/src/styles/main.css`.
- This class builds a complex multi-layered background image stack:
- **Layer 1**: Vertical Repeating Rainbow (`0deg` linear gradient).
- **Layer 2**: Diagonal Texture (`133deg` repeating linear gradient with hard-light/hue stops).
- Uses `background-blend-mode: screen, hue` to mix these layers dynamically.
- Uses `mix-blend-mode: color-dodge` to composite onto the card image.
- Includes a custom animation `foil-shift` (15s linear infinite) that shifts the background position vertically and diagonally, creating an "always active" shimmering effect.
- **CardPreview Update**:
- Updated `FoilOverlay` to use the `.foil-holo` class.
- Retained the **Gaussian Circular Glare** (`radial-gradient` + `animate-spin-slow`) as a top-layer "spotlight" effect.
## Result
The foil effect is now significantly more intricate, featuring vertical color bands and diagonal textures that shift over time, mimicking the look of high-end TCG holofoils (like "Secret Rares" or "Full Arts").

View File

@@ -1,18 +0,0 @@
# Universal Preview Animations
## Objective
Implement graceful appearing and disappearing animations for card previews on **all** screens (Desktop + Mobile), ensuring a polished feel uniform across the platform.
## Changes
- Modified `src/client/src/components/CardPreview.tsx`:
- **CardHoverWrapper**: Updated the logic for `shouldShow` state management. Removed the `isMobile` restriction on the exit delay. Now, **all devices** respect the 300ms unmount timeout, giving the exit animation time to play before the component is removed from the DOM.
- **FloatingPreview (Desktop Mode)**:
- Added `transition-all duration-300` to the desktop container's inner div.
- Applied dynamic classes based on `isClosing`:
- **Entering**: `scale-100 opacity-100 ease-out`
- **Exiting**: `scale-95 opacity-0 ease-in`
- This effectively replicates the "pop-in / pop-out" animation that was previously mobile-only.
- Fixed duplicated syntax errors introduced during the update logic.
## Result
On desktop, hovering over a card now triggers a smooth scale-up phase-in. When the mouse leaves, the card preview shrinks slightly and fades out gracefully rather than disappearing instantly. This matches the mobile long-press behavior.

View File

@@ -1,16 +0,0 @@
# Mobile Touch Interaction Logic
## Objective
Enhance mobile usability by modifying the long-press behavior. The preview should persist while the user moves their finger across the screen (e.g., to inspect different parts of the card or simply drift) and only disappear upon releasing the finger (`touchend`).
## Changes
- Modified `src/client/src/components/CardPreview.tsx`:
- Updated `handleTouchMove` in `CardHoverWrapper`.
- Removed the `setIsLongPressing(false)` call inside the movement threshold check.
- **Logic**:
- If the user moves their finger *before* the 500ms long-press timer completes, the timer is cleared (canceling the preview), interpreting the action as a scroll.
- If the user moves their finger *after* the preview has appeared (`isLongPressing` is true), the movement is ignored, and the preview **remains visible**.
- The preview is now effectively closed only by `handleTouchEnd` (lifting the finger).
## Result
This creates a much more forgiving and "tactile" experience on mobile, allowing users to hold their thumb on a card and shift it slightly without the preview abruptly vanishing.

View File

@@ -1,17 +0,0 @@
# Entrance Animation Fix
## Objective
Ensure the card preview plays the "scale-up fade-in" animation when it first appears (mounting), not just when disappearing.
## Changes
- Modified `FloatingPreview` in `src/client/src/components/CardPreview.tsx`:
- Introduced a generic `isMounted` state initialized to `false`.
- Added a `useEffect` that sets `isMounted` to `true` on the next animation frame after mount.
- Updated CSS logic to check a combined `isActive` state (`isMounted && !isClosing`).
- **Logic**:
- **Mount (0ms)**: `isActive` is false `->` `opacity-0 scale-95`.
- **Next Frame (~16ms)**: `isMounted` becomes true `->` `isActive` becomes true `->` `transition-all` triggers to `opacity-100 scale-100`.
- **Unmount Trigger**: `isClosing` becomes true `->` `isActive` becomes false `->` Transitions back to `opacity-0 scale-95`.
## Result
The card preview now smoothly "pops in" from 95% scale and 0 opacity every time it is triggered, providing a consistent, high-quality feel to the UI interactions.

View File

@@ -1,13 +0,0 @@
# Bug Fix: Unconditional Foil Overlay
## Objective
Correct the issue where foil holographic animations were appearing on non-foil cards in the desktop view.
## Changes
- Modified `FloatingPreview` in `src/client/src/components/CardPreview.tsx`:
- In the desktop return block, the code manually embedding the foil effect divs (introduced in a previous step) was missing the `{isFoil && ...}` conditional wrapper.
- Replaced the manual div insertion with the `<FoilOverlay />` component, which encapsulates the foil logic correctly.
- Wrapped this component call in the `{isFoil && <FoilOverlay />}` check to ensure it only renders for cards with `foil` or `etched` finishes.
## Result
Foil animations now strictly adhere to card metadata, appearing only on actual foil cards as intended. Normal cards display cleanly without any holographic overlay.

View File

@@ -1,16 +0,0 @@
### Replaced Alert with Toast Notification
**Status**: Completed
**Date**: 2025-12-17
**Description**
Replaced the invasive `alert()` on the "Copy Pack" button with a non-intrusive Toast notification.
**Changes**
1. Created `src/client/src/components/Toast.tsx` with a `ToastProvider` and `useToast` hook.
2. Wrapped `App.tsx` with `ToastProvider`.
3. Updated `PackCard.tsx` to use `showToast` instead of `alert`.
**Next Steps**
- Consider replacing other alerts in `CubeManager` with Toasts for consistency.

View File

@@ -1,16 +0,0 @@
# Universal Foil Animation
## Objective
Apply the high-fidelity foil animation to **all** card image instances, including the "Grid View" and "Stack View" thumbnails, not just the magnified hover preview.
## Changes
- **CardPreview.tsx**: Exported the `FoilOverlay` component so it can be reused across the application.
- **PackCard.tsx**:
- Imported `FoilOverlay`.
- Replaced the previous generic static foil gradient in `Grid View` with the `<FoilOverlay />` component.
- **StackView.tsx**:
- Imported `FoilOverlay`.
- Replaced the simple opacity layer for foil cards with the `<FoilOverlay />` component.
## Result
Now, whenever a foil card is displayed on the screen—whether as a thumbnail in a pack grid, a card in a stack pile, or a magnified preview—it consistently features the generic holographic animation and rotating glare effect.

View File

@@ -1,21 +0,0 @@
### Enhanced Toast Visibility
**Status**: Completed
**Date**: 2025-12-17
**Description**
Updated the Toast notification to be more prominent and centrally located, as per user feedback.
**Changes**
1. **Position**: Moved from bottom-right to top-center (`top-6 left-1/2 -translate-x-1/2`).
2. **Animation**: Changed to `slide-in-from-top-full` with a slight zoom-in effect.
3. **Styling**:
- Increased padding (`px-6 py-4`).
- Increased border width (`border-2`) and brightness.
- Added stronger shadows (`shadow-2xl`).
- Increased contrast for text and background.
- Increased font weight to `bold`.
**Effect**
Notifications are now impossible to miss, appearing top-center with a premium, game-like alert style.

View File

@@ -1,16 +0,0 @@
# Intelligent Preview Suppression
## Objective
Prevent the card preview popup from appearing when the user hovers over a card that is already displayed at a significantly large size on the screen (e.g., in a large grid view), reducing UI clutter.
## Changes
- Modified `CardHoverWrapper` in `src/client/src/components/CardPreview.tsx`:
- Updated `handleMouseEnter` to inspect the dimensions of the hovered element using `getBoundingClientRect`.
- Implemented a threshold check: `Width > 240px` AND `Height > 300px`.
- **Logic**:
- **Large Grid Items**: If a card in the grid is rendered wider than 240px and taller than 300px, the hover preview is suppressed.
- **List Items**: Even if a list row is wide (e.g., 800px), its height is small (e.g., 40px), so the preview **will still appear**.
- **Small Thumbnails**: Small grid items or stack views usually fall below this threshold, ensuring the preview appears when needed.
## Result
The system now intelligently hides the preview when it is redundant, creating a cleaner experience on large desktop screens while maintaining necessary functionality for smaller thumbnails and list views.

View File

@@ -1,18 +0,0 @@
# Compact Card Layout
## Objective
Slightly resize the card visualizations in both Grid and Stack views to allow more cards to fit on the screen, creating a denser and more "compact" interface as requested.
## Changes
- **Pack Grid View** (`src/client/src/components/PackCard.tsx`):
- Increased the column density across all breakpoints:
- Base: `grid-cols-2` -> `grid-cols-3`
- Small: `grid-cols-3` -> `grid-cols-4`
- Medium: `grid-cols-4` -> `grid-cols-5`
- Large: `grid-cols-5` -> `grid-cols-6`
- This reduces the individual card width, making them visually smaller.
- **Stack / Deck View** (`src/client/src/components/StackView.tsx`):
- Reduced the fixed width of each stack column from `w-44` (176px) to `w-36` (144px).
## Result
Cards appear slightly smaller ("a little more smaller"), providing a broader overview of the pool and deck without requiring as much scrolling. This works in tandem with the "Smart Preview Suppression" (which will likely now re-enable previews for these smaller cards, aiding readability).

View File

@@ -1,17 +0,0 @@
### Unified Toast Design
**Status**: Completed
**Date**: 2025-12-17
**Description**
Refined the Toast notification design to align perfectly with the "Dark Gaming Aesthetic" of the platform.
**Changes**
1. **Consistent Palette**: Switched to `bg-slate-800` (cards) with `border-slate-700` equivalents, using colored accents only for borders and icons.
2. **Icon Enclosure**: Icons are now housed in a circular, semi-transparent colored background (`bg-emerald-500/10`) for a polished look.
3. **Typography**: Reverted to standard font weights used in other UI cards (`font-medium`) for better readability and consistency.
4. **Shadows**: Tuned shadows to be deep but subtle (`shadow-2xl shadow-emerald-900/20`), matching the ambient lighting of the app.
**Effect**
The Toast now feels like a native part of the UI rather than a generic alert overlay.

View File

@@ -1,20 +0,0 @@
### Animated Copy Button
**Status**: Completed
**Date**: 2025-12-17
**Description**
Replaced the toast notification for the copy action with a self-contained, animated button state.
**Changes**
1. **Removed Toast Usage**: Detached `useToast` from `PackCard.tsx`.
2. **Local State**: Implemented `copied` state in `PackCard`.
3. **UI Feedback**:
- Button transitions from "Copy" (slate) to "Check" (emerald/green) on click.
- Added `animate-in zoom-in spin-in-12` for a satisfying "tick" animation.
- Button background and border glow green to confirm success.
- Auto-reverts after 2 seconds.
**Effect**
Provides immediate, localized feedback for the copy action without clogging the global UI with notifications.

View File

@@ -1,19 +0,0 @@
# View Scale Slider
## Objective
Provide the user with granular control over card thumbnail sizes across the application, ensuring consistency between Grid and Stack views.
## Changes
- **CubeManager**:
- Added a new `cardWidth` state variable, persisted to `localStorage` (default `140px`).
- Introduced a **Range Slider** in the top-right control toolbar (visible on desktop) allowing adjustment from 100px to 300px.
- Passed `cardWidth` down to `PackCard`.
- **PackCard (Grid View)**:
- Replaced the responsive `grid-cols-*` logic with a `flex flex-wrap` layout.
- Each card container now receives an explicit `style={{ width: cardWidth }}`.
- **StackView (Stack View)**:
- Accepted `cardWidth` prop.
- Applied `style={{ width: cardWidth }}` to the column containers, dynamically ensuring that stacks resize in sync with the grid view setting.
## Result
Users can now drag a slider to instantly resize all card thumbnails on the screen. This allows for customized density—make cards huge to admire the art, or tiny to see the entire cube/pool at a glance—with perfect size synchronization between the different view modes.

View File

@@ -1,18 +0,0 @@
# Dynamic Art Cropping
## Objective
Automatically switch card visualizations to "Full Art" (Art Crop) mode when the thumbnail size is reduced below a readability threshold, maximizing the visual impact of the artwork when text is too small to read.
## Changes
- **Backend (Client & Server)**:
- Updated `DraftCard` interface to include `imageArtCrop`.
- Modified parsing services (`PackGeneratorService`) to extract and populate `imageArtCrop` from Scryfall data.
- **Frontend (UI)**:
- **PackCard (Grid View)**: Implemented a conditional check: if `cardWidth < 170px`, the image source switches to `imageArtCrop`.
- **StackView (Deck/Collection)**: Applied the same logic.
- **Visuals**:
- The `object-cover` CSS property ensures the rectangular art crop fills the entire card frame, creating a "borderless/full-art" look.
- The **Foil Overlay** and **Rarity Stripe** remain visible on top of the art crop, maintaining game state clarity.
## Result
As you slide the size slider down, the cards seamlessly transform from standard cards (with borders and text) to vibrant, full-art thumbnails. This creates a stunning "mosaic" effect for the cube overview and deck stacks, solving the issue of illegible text at small scales.

View File

@@ -1,22 +0,0 @@
# Bug Fix: Pack Generation Limits in From Expansion Mode
## Issue
The user reported that when generating "1 Box" (36 packs) in "From Expansion" mode, only about 10 packs were generated.
This was caused by the pack generation algorithm treating the card pool as finite (consuming cards as they are picked). Since Scryfall data usually provides a singleton list (1 copy of each card), the pool of Commons would deplete rapidly (e.g., 10 packs * 10 commons = 100 commons), halting generation when unique commons ran out.
## Solution
Implemented a "Unlimited Pool" / "With Replacement" mode for pack generation.
- **Server (`PackGeneratorService.ts`)**: Added `withReplacement` flag to `PackGenerationSettings`.
- When enabled, the generator creates a FRESH copy of the shuffled pool for EACH pack.
- This simulates a "Retail Draft" or "Print Run" scenario where packs are independent samples from a large supply, rather than drawing from a fixed, finite Cube.
- Uniqueness is still enforced WITHIN each pack (no duplicate cards in the same pack).
- **Client (`CubeManager.tsx`)**: updated the payload to strictly enable `withReplacement: true` whenever `sourceMode` is set to "From Expansion" ("set").
## Files Modified
- `src/server/services/PackGeneratorService.ts`: Implemented replacement logic.
- `src/client/src/modules/cube/CubeManager.tsx`: Updated API call payload.
- `src/client/src/services/PackGeneratorService.ts`: Updated interface definitions.
## Status
- [x] Fix Implemented
- [x] Verified Logic

View File

@@ -1,17 +0,0 @@
# Mobile Long Press Card Preview
## Status
- [x] Research current implementation of `PackCard` and `CardPreview`
- [x] Implement long-press detection in `PackCard` (Found existing implementation in `CardPreview`)
- [x] Prevent default browser context menu on card images
- [x] Trigger preview on long-press only for small screens (or generally if touch)
- [x] Verify implementation
## Context
User reported that long-pressing a card on mobile opens the browser menu (download image context menu).
Goal: Long press should show the card preview instead.
## Implementation Details
- Modified `CardHoverWrapper` in `CardPreview.tsx` to prevent `contextmenu` event default behavior on mobile devices when an image is present.
- This ensures the custom long-press timer has time to trigger the preview without the system menu interfering.
- Logic uses `isMobile && hasImage` to target specific scenario.

View File

@@ -1,16 +0,0 @@
# Mobile Card Size Slider
## Status
- [x] Locate the card size slider component (`CubeManager` and `DraftView`)
- [x] Analyze why it is hidden on small screens (`hidden` utility classes)
- [x] Modify layout to ensure it is visible on mobile
- [x] Determine if layout adjustments are needed (Reduced width on `DraftView`)
- [x] Verify implementation (Code applied)
## Context
User reported that the card size adjustment bar is missing on small screens.
The fix was applied to both the Cube Manager (pack review) and Draft View (live drafting).
## Changes
- **CubeManager.tsx**: Removed `hidden sm:flex` from the slider container. It is now always `flex`.
- **DraftView.tsx**: Removed `hidden md:flex` and adjusted width to `w-24 md:w-32` to fit better on small screens.

View File

@@ -1,14 +0,0 @@
# Refined Preview Suppression
## Objective
Tune the "Smart Preview Suppression" logic to better align with the Stack View's behavior. In Stack View, hovering a card causes it to "pop" to the front (`z-index` shift), making the card fully visible in-place. Because of this, showing a floating preview is redundant and distracting once the card is large enough to be read directly.
## Changes
- Modified `handleMouseEnter` in `src/client/src/components/CardPreview.tsx`:
- Lowered the suppression threshold from `>240x300` to `>200x270`.
- **Logic**:
- Cards sized via the slider to be larger than **200px** wide are now considered "readable" (especially since the 'Art Crop' mode turns off at 170px, leaving a range of 170-199 where preview is explicitly ON for text, and 200+ where it's suppressed).
- This effectively disables the popup in Stack View for medium-to-large settings, relying on the native "pop-to-front" hover effect for inspection.
## Result
A cleaner, less jittery drafting experience where large cards simply "lift up" for inspection, while smaller cards still get the helpful magnified popup.

View File

@@ -1,19 +0,0 @@
# 2025-12-17 Change Default Filter Flags
## Objective
Change the default state of the "Ignore Basic Lands", "Ignore Commander Sets", and "Ignore Tokens" flags from checked (true) to unchecked (false) to match user preference.
## Changes
1. **Client-Side (`src/client/src/modules/cube/CubeManager.tsx`)**:
* Updated the initial state of the `filters` object.
* The defaults for `ignoreBasicLands`, `ignoreCommander`, and `ignoreTokens` are now `false`.
* This affects new users or sessions where `localStorage` does not have saved preferences.
2. **Server-Side (`src/server/index.ts`)**:
* Updated the default fallback values for `filters` in the `/api/packs/generate` route.
* If no filters are provided in the request payload, the server now defaults these flags to `false`.
## Verification
* Verified that the variable names match the UI labels.
* Verified that the logic correctly implements "unchecked" by setting the boolean values to `false`.

View File

@@ -1,16 +0,0 @@
# Explicit Preview Suppression
## Objective
Enforce strict preview suppression when card sizes are large (`>= 200px`), regardless of element visibility, overlap, or DOM layout quirks. This ensures that in Stack View, where cards overlap, no stray previews are triggered for cards that are ostensibly "big enough" to be read directly.
## Changes
- **CardPreview (`CardHoverWrapper`)**:
- Added an optional `preventPreview?: boolean` prop.
- Updated `handleMouseEnter` to immediately return if `preventPreview` is true, bypassing any DOM size checks that might be inaccurate for obscured elements.
- **PackCard (Grid View)**:
- Passed `preventPreview={cardWidth >= 200}` to the wrapper.
- **StackView (Stack View)**:
- Passed `preventPreview={cardWidth >= 200}` to the wrapper.
## Result
Total consistency: if your slider is set to 200/300, floating previews are globally disabled for those views. This specifically fixes the issue where overlapping cards in a stack might have triggered previews unnecessarily.

View File

@@ -1,13 +0,0 @@
# Synchronized Display Boundaries
## Objective
Harmonize the "Full Art" visualization mode with the specific behavior of the slider and preview suppression logic.
## Changes
- **Threshold Update**: Shifted the trigger point for Art Crop visualization (full art thumbnails) from `170px` to **`200px`**.
- This corresponds to exactly **50% of the slider range** (100px-300px), creating a predictable user interface boundary.
- **< 200px**: Cards display as **Art Crops (Full Art)** because text would be illegible. **Hover Preview is Enabled** to show the card details.
- **>= 200px**: Cards display as **Standard Scryfall Images** (with borders/text) because text is legible. **Hover Preview is Disabled** to prevent redundancy, as the card itself acts as the reference.
## Result
A unified "Pivot Point" at 200px. Sliding left gives you a dense, artistic mosaic with helpful popups. Sliding right gives you a readable, "tabletop" view with direct card interaction and no popup clutter.

View File

@@ -1,16 +0,0 @@
# Squared Art Crops
## Objective
Optimize the "Full Art" display mode by switching from a rectangular card ratio to a square ratio. This focuses the view on the artwork itself (which is typically landscape/square-ish in crops) and provides a more compact, tile-like aesthetic for small thumbnails.
## Changes
- **Grid View (`PackCard`)**:
- Dynamically switches CSS classes: uses `aspect-square` when in Art Crop mode (<200px), and `aspect-[2.5/3.5]` (standard card ratio) otherwise.
- Creates a uniform grid of square tiles for the visual overview.
- **Stack View (`StackView`)**:
- Dynamically adjusts inline styles:
- `aspectRatio`: Switches between `'1/1'` and `'2.5/3.5'`.
- `marginBottom` (for stacking overlap): Adjusted from `-125%` (for tall rectangles) to `-85%` (for squares) to maintain a consistent visible "header strip" for cards underneath.
## Result
When you slide the size down, the cards now morph into neat square tiles. This maximizes the art visibility within the small space and makes the "mosaic" feel even more deliberate and organized.

View File

@@ -1,45 +0,0 @@
# Strict Pack Generation Logic Fix
## Objective
Fix the pack generation algorithm to strictly enforce pack sizes and composition rules. Ensure that "Standard" packs have exactly 14 cards and "Peasant" packs have exactly 13 cards. Any generation attempt that fails to meet these criteria due to card depletion must result in the termination of the generation process for that set, rather than producing partial/invalid packs.
## Current Issues
1. **Partial Packs**: The current generator continues to produce packs even when specific rarity pools (like Rares for Standard) are depleted, resulting in packs with fewer than the required number of cards.
2. **Fallbacks**: The logic currently "falls back" to lower rarities (e.g., Common instead of List/Wildcard) to fill slots, which might violate "Strict" adherence if not desired.
3. **Size limit**: Packs are not strictly truncated or validated against the target size (14 or 13).
## Proposed Changes
### `PackGeneratorService.ts`
1. **Refactor `buildSinglePack`**:
- define `targetSize` based on `rarityMode` (14 for Standard, 13 for Peasant).
- **Slot 7 (List)**: Remove fallback to Common if Uncommon/List pool is empty. If the strict RNG calls for a List card and none are available, the slot remains empty (causing validation failure).
- **Wildcards**: Remove fallback to Common if the rolled rarity pool is empty.
- **Peasant Isolation**: Explicitly restrict Peasant Wildcards to Common/Uncommon only (No Rares/Mythics under any RNG circumstance).
- **Strict Validation**: At the end of pack construction, check if `packCards.length` is less than `targetSize`. If so, return `null`.
- **Truncation**: Slice the `packCards` array to `targetSize` to ensure no "exceeding" cards (like Tokens or extra Wildcards) are included beyond the strict limit.
2. **Algorithm Details**:
- **Standard**: 14 Cards.
- Slots 1-6: Commons
- Slot 7: Common/List
- Slots 8-10: Uncommons
- Slot 11: Rare/Mythic
- Slot 12: Land
- Slot 13: Wildcard
- Slot 14: Foil Wildcard
- (Slot 15 Token ignored/truncated)
- **Peasant**: 13 Cards.
- Slots 1-6: Commons
- Slot 7: Common/List
- Slots 8-11: Uncommons
- Slot 12: Land
- Slot 13: Wildcard (Common/Uncommon ONLY)
- (Slot 14 Foil WC ignored/truncated)
- (Slot 15 Token ignored/truncated)
3. **Behavior**:
- If `buildSinglePack` returns `null`, the `generatePacks` loop will `break` (stop), preventing the creation of any further illegal packs from that pool.
## Verification
- Run `npm run build` to ensure compilation.
- (Manual) Verify in Draft App that generating from a small pool stops correctly when Rares run out.

View File

@@ -1,14 +0,0 @@
# 2025-12-17 Left Sidebar Max Width
## Objective
Limit the left sidebar in the Cube Manager to a maximum width of 400px on large screens to prevent it from becoming excessively wide on high-resolution displays.
## Changes
1. **Layout Refactor (`src/client/src/modules/cube/CubeManager.tsx`)**:
* Change the main container from a CSS Grid (`grid-cols-12`) to a Flexbox layout (`flex-col lg:flex-row`).
* Set the left column width to `lg:w-1/3` with a strict `lg:max-w-[400px]` constraint.
* Set the right column to `flex-1` to take up remaining space.
## Rationale
The previous `lg:col-span-4` (33% width) scaled indefinitely on large screens (e.g., 2560px wide -> ~850px sidebar), which wastes space and stretches control inputs. A max-width constraint ensures the controls remain compact while the main content area (packs display) benefits from the extra screen real estate.

View File

@@ -1,19 +0,0 @@
### Play Online Logic Implementation
**Status**: Completed
**Date**: 2025-12-17
**Description**
Implemented pack count validation logic for "Play Online" to strictly enforce draft player limits.
**Changes**
1. **Rule Enforcement**:
- **< 12 packs**: Button visual disabled (slate color), shows error toast explaining rules if clicked.
- **12-17 packs**: Allows entry, shows toast "Enough for 4 players only" (Info).
- **18-23 packs**: Allows entry, shows toast "Enough for 4 or 6 players" (Info).
- **24+ packs**: Allows entry, shows toast "Enough for 8 players!" (Success).
2. **UI Feedback**: Updated button class logic to visually reflect availability based on pack count.
**Effect**
Prevents users from starting unplayable drafts and informs them of the capacity their current pool supports.

View File

@@ -1,16 +0,0 @@
### Lobby Rules Tooltip
**Status**: Completed
**Date**: 2025-12-17
**Description**
Added a dynamic tooltip and status indicator to the Online Lobby to explain draft capacity rules based on pack count.
**Changes**
1. **Info Icon**: Added an `AlertCircle` icon with a hoverable tooltip explaining the pack requirements (3 packs/player).
2. **Dynamic Rules**: The list of rules highlights the currently applicable tier based on pack count (e.g., turning green for "12-17 Packs" if 15 packs are available).
3. **Status Line**: A summary line explicitly states "Supported Players: [Status]" under the pack count.
**Effect**
Users can now clearly see why they might need more packs before creating a room, and what player counts are supported with their current pool.

View File

@@ -1,22 +0,0 @@
# Fix Expansion Pack Generation (Infinite Cards)
## Problem
The user reported two issues with "From Expansion" pack generation:
1. Incorrect amount of packs generated (e.g., 10 instead of 36).
2. The generator was using a finite pool of cards (like a custom cube) instead of an infinite supply (like opening fresh packs).
## Root Cause
The `PackGeneratorService` defaults to generating packs without replacement (`withReplacement: false`). This means once a card is used, it is removed from the pool.
For a standard set (Expansion), the pool contains only one copy of each card (from Scryfall fetch).
When generating a large number of packs (e.g., 36 for a box), the rare/mythic/uncommon pools would deplete quickly, causing the generator to stop early and produce fewer packs than requested.
## Solution
Modified `src/server/index.ts` to enforce `settings.withReplacement = true` when `sourceMode === 'set'`.
This ensures that:
- The pack generator refreshes the card pools for every new pack.
- Generating 36 packs (or any number) is possible even from a single set of source cards.
- Duplicates are allowed across packs (simulating a print run), while maintaining uniqueness within a single pack (handled by `buildSinglePack`).
## Changes
- **File**: `src/server/index.ts`
- **Logic**: Added a check in the `/api/packs/generate` route to set `settings.withReplacement = true` if `sourceMode === 'set'`.

View File

@@ -0,0 +1,16 @@
# Enable Clear Session Button in Pack Generator
## Object
Enable and improve the "Clear Session" button in the Cube Manager (Pack Generator) to allow users to restart the generation process from a clean state.
## Changes
- Modified `CubeManager.tsx`:
- Updated `handleReset` logic (verified).
- enhanced "Clear Session" button styling to be more visible (red border/text) and indicate its destructive nature.
- Added `disabled={loading}` to prevent state conflicts during active operations.
- **Replaced `window.confirm` with a double-click UI confirmation pattern** to ensure reliability and better UX (fixed issue where native confirmation dialog was failing).
## Status
- [x] Implementation complete.
- [x] Verified logic for `localStorage` clearing.
- [x] Verified interaction in browser (button changes state, clears data on second click).

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
Slots 1-6 (Commons): 6 Common cards. Ensure color balance (attempt to include at least 3 distinct colors).
Slot 7 (Common/List Slot):
- Roll a d100.
- 1-87: 1 Common from Main Set.
- 88-97: 1 Card from "The List" (Common/Uncommon reprint).
- 98-100: 1 Uncommon from "The List".
Slots 8-11 (Uncommons): 4 Uncommon cards.
Slot 12 (Land): 1 Basic or Common Dual Land (20% chance of Foil).
Slot 13 (Non-Foil Wildcard):
- Can be any rarity (Common, Uncommon, Rare, Mythic).
- Use weighted probability: ~62% Common, ~37% Uncommon.
- Can be a card from the child sets.
Slot 14 (Foil Wildcard):
- Same rarity weights as Slot 13, but the card must be Foil.
Slot 15 (Marketing): Token or Art Card.

View File

@@ -0,0 +1,20 @@
Slots 1-6 (Commons): 6 Common cards. Ensure color balance (attempt to include at least 3 distinct colors).
Slot 7 (Common/List Slot):
- Roll a d100.
- 1-87: 1 Common from Main Set.
- 88-97: 1 Card from "The List" (Common/Uncommon reprint).
- 98-99: 1 Rare/Mythic from "The List".
- 100: 1 Special Guest (High Value).
Slots 8-10 (Uncommons): 3 Uncommon cards.
Slot 11 (Main Rare Slot):
- Roll 1d8.
- If 1-7: Rare.
- If 8: Mythic Rare.
Slot 12 (Land): 1 Basic or Common Dual Land (20% chance of Foil).
Slot 13 (Non-Foil Wildcard):
- Can be any rarity (Common, Uncommon, Rare, Mythic).
- Use weighted probability: ~49% Common, ~24% Uncommon, ~13% Rare, ~13% Mythic.
- Can be a card from the child sets.
Slot 14 (Foil Wildcard):
- Same rarity weights as Slot 13, but the card must be Foil.
Slot 15 (Marketing): Token or Art Card.

View File

@@ -43,7 +43,8 @@ service:
ingress:
enabled: false
className: ""
annotations: {}
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:

4
src/.env.example Normal file
View File

@@ -0,0 +1,4 @@
GEMINI_API_KEY=your_gemini_api_key_here
GEMINI_MODEL=gemini-2.0-flash-lite-preview-02-05
USE_LLM_PICK=true

Some files were not shown because too many files have changed in this diff Show More