Compare commits
37 Commits
8995c3f7e8
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 4e36157115 | |||
| 139aca6f4f | |||
| 418e9e4507 | |||
| eb453fd906 | |||
| 2794ce71aa | |||
| 664d0e838d | |||
| a3e45b13ce | |||
| fd20c3cfb2 | |||
| 412f696646 | |||
| 1853fd9e28 | |||
| c9266b9604 | |||
| 4585e2a944 | |||
| 7b47d566c2 | |||
| 312530d0f0 | |||
| 755ae73d9e | |||
| 49080d8233 | |||
| bc5eda5e2a | |||
| ca7b5bf7fa | |||
| 842beae419 | |||
| a2a45a995c | |||
| e31323859f | |||
| 87e38bd0a3 | |||
| 6b054ad8fc | |||
| b39da587d4 | |||
| 78af33ec99 | |||
| 6301e0e7f5 | |||
| 642e203baf | |||
| d27cc625e4 | |||
| b7e0d1479c | |||
| bd33f6be24 | |||
| e6e452b030 | |||
| db601048d9 | |||
| ebfdfef5ae | |||
| 851e2aa81d | |||
| 0ca29622ef | |||
| d550bc3d04 | |||
| 12e60d42f3 |
@@ -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.
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -141,3 +141,4 @@ vite.config.ts.timestamp-*
|
||||
.vite/
|
||||
|
||||
src/server/public/cards/*
|
||||
src/server-data
|
||||
@@ -1,96 +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.
|
||||
- [Responsive Pack Grid Layout](./devlog/2025-12-17-142500_responsive_pack_grid.md): Completed. Implemented responsive multi-column grid for generated packs when card size is reduced (<25% slider).
|
||||
- [Stack View Consistency Fix](./devlog/2025-12-17-143000_stack_view_consistency.md): Completed. Removed transparent overrides for Stack View, ensuring it renders with the standard unified container graphic.
|
||||
- [Dynamic Pack Grid Layout](./devlog/2025-12-17-144000_dynamic_pack_grid.md): Completed. Implemented responsive CSS grid with `minmax(550px, 1fr)` for Stack/Grid views to auto-fit packs based on screen width without explicit column limits.
|
||||
- [Fix Socket Payload Limit](./devlog/2025-12-17-152700_fix_socket_payload_limit.md): Completed. Increased Socket.IO `maxHttpBufferSize` to 300MB to support massive drafting payloads.
|
||||
- [Basic Lands Handling](./devlog/2025-12-17-153300_basic_lands_handling.md): Completed. Implemented flow to cache and provide set-specific basic lands for infinite use during deck building.
|
||||
- [Land Advice & Unlimited Time](./devlog/2025-12-17-155500_land_advice_and_unlimited_time.md): Completed. Implemented land suggestion algorithm and disabled deck builder timer.
|
||||
- [Deck Builder Magnified View](./devlog/2025-12-17-160500_deck_builder_magnified_view.md): Completed. Added magnified card preview sidebar to deck builder.
|
||||
- [Gameplay Magnified View & Timeout](./devlog/2025-12-17-161500_gameplay_magnified_view_and_timeout.md): Completed. Added magnified view with full card details (Oracle text, type, mana) to gameplay and disabled timeout.
|
||||
- [Test Deck Feature](./devlog/2025-12-17-162500_test_deck_feature.md): Completed. Implemented "Test Solo" button in Cube Manager to instantly start a solo game with a randomized deck from generated packs.
|
||||
- [Update Deck Auto-Fill](./devlog/2025-12-17-165500_update_deck_autofill.md): Completed. Updated deck builder "Auto-Fill" to add lands as individual cards to the deck list for easier management.
|
||||
- [2025-12-17-183000_restore_stack_hover](./devlog/2025-12-17-183000_restore_stack_hover.md): Completed. Restored hover magnified card for Stack View in Pack Generation.
|
||||
- [2025-12-17-183500_draft_ui_upgrade](./devlog/2025-12-17-183500_draft_ui_upgrade.md): Completed. Implemented 3D flip preview and consistent foil rendering in Draft View.
|
||||
- [2025-12-17-184000_fix_draft_pool_ui](./devlog/2025-12-17-184000_fix_draft_pool_ui.md): Completed. Fixed "Your Pool" resizing bugs and removed unwanted hover animation.
|
||||
- [Customizable Deck Builder Layout](./devlog/2025-12-17-170000_customizable_deck_builder.md): Completed. Implemented switchable Vertical (Side-by-Side) and Horizontal (Top-Bottom) layouts, with an integrated, improved Land Station.
|
||||
- [Draft View Layout Selection](./devlog/2025-12-17-185000_draft_view_layout.md): Completed. Implemented Vertical/Horizontal layout selection for Draft View to match Deck Builder, optimizing screen space and preventing overlap.
|
||||
- [Fix Cube Sidebar Scrolling](./devlog/2025-12-18-004109_fix_cube_sidebar_scrolling.md): Completed. Adjusted sidebar max-height to ensure autonomous scrolling and button accessibility on tablet screens.
|
||||
- [PWA Install Prompt](./devlog/2025-12-18-004600_pwa_install_prompt.md): Completed. Implemented `PWAInstallPrompt` component in `App.tsx` and enabled PWA dev options.
|
||||
- [Fix PWA Install Prompt](./devlog/2025-12-18-005000_fix_pwa_prompt.md): Completed. Implemented global event capture, iOS detection, and explicit service worker registration to ensure install prompt appears.
|
||||
- [Persist PWA Dismissal](./devlog/2025-12-18-005300_persist_pwa_dismissal.md): Completed. Implemented logic to remember user's choice to dismiss or install the PWA, preventing repeated prompts.
|
||||
- [Create Favicon](./devlog/2025-12-18-005739_create_favicon.md): Completed. Generated and integrated a new application favicon.
|
||||
## Devlog Index
|
||||
- [Enable Clear Session](./devlog/2025-12-20-014500_enable_clear_session.md) - Improved UI/UX for session clearing in CubeManager.
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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".
|
||||
@@ -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.
|
||||
@@ -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").
|
||||
@@ -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).
|
||||
@@ -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.
|
||||
@@ -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).
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.).
|
||||
@@ -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`).
|
||||
@@ -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).
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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).
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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").
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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).
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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`.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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'`.
|
||||
@@ -1,20 +0,0 @@
|
||||
# Responsive Pack Grid Layout
|
||||
|
||||
## Objective
|
||||
Update the generated packs UI to maximize pack density on screen when the user reduces the card size.
|
||||
|
||||
## Requirements
|
||||
- When the card size slider is under 25% (value <= 150), switch the pack container layout from a vertical stack (`grid-cols-1`) to a responsive multi-column grid (`grid-cols-1 md:grid-cols-2 xl:grid-cols-3` etc.).
|
||||
- Ensure this applies to all view modes (List, Grid, Stack).
|
||||
- Maintain consistency in UI.
|
||||
|
||||
## Implementation
|
||||
- Modified `src/client/src/modules/cube/CubeManager.tsx`.
|
||||
- Added conditional logic to the main packs container `div`.
|
||||
- Condition: `cardWidth <= 150`.
|
||||
- Classes: `grid-cols-1 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4` for compact mode.
|
||||
|
||||
## Verification
|
||||
- Verified using browser simulation.
|
||||
- Verified that setting slider to 100 triggers the grid layout.
|
||||
- Verified that setting slider to 300 reverts to vertical stack.
|
||||
@@ -1,17 +0,0 @@
|
||||
# Stack View Consistency Fix
|
||||
|
||||
## Objective
|
||||
Ensure the Stack View pack container has the same visual styling (background, border, shadow, header) as the List and Grid views.
|
||||
|
||||
## User Request
|
||||
"the stacked view region graphic is not consistent with the other views, the container region is missing"
|
||||
|
||||
## Implementation
|
||||
- Modified `src/client/src/components/PackCard.tsx`.
|
||||
- Removed the conditional ternary operators that stripped the background and border when `viewMode === 'stack'`.
|
||||
- Ensured consistent `p-4` padding for the content wrapper.
|
||||
- The `StackView` component is now rendered inside the standard slate card container.
|
||||
|
||||
## Verification
|
||||
- Code review confirms the removal of `bg-transparent border-none` overrides.
|
||||
- This ensures the `bg-slate-800` class applied to the parent `div` is visible in all modes.
|
||||
@@ -1,19 +0,0 @@
|
||||
# Dynamic Pack Grid Layout
|
||||
|
||||
## Objective
|
||||
Implement a truly dynamic, screen-dependent pack grid layout for Stack and Grid views to satisfy the requirement: "implement the grid to have dynamic number of packs in a single row based on the screen width".
|
||||
|
||||
## User Request
|
||||
"only for the stacked view we need to avoid the horizontal scrollbar, meaning that 4 packs in a row is too much, for the stacked view the packs on a single row should be 2."
|
||||
"now implement the grid to have dynamic number of packs in a single row based on the screen width"
|
||||
|
||||
## Implementation
|
||||
- Modified `src/client/src/modules/cube/CubeManager.tsx`.
|
||||
- Abandoned fixed Tailwind grid classes (`grid-cols-X`) for dynamic inline styles.
|
||||
- Utilized CSS Grid `repeat(auto-fill, minmax(..., 1fr))` syntax.
|
||||
- **Rules per view**:
|
||||
- **List View**: `minmax(320px, 1fr)`. Allows multiple compact columns (up to 4+ on ultrawide).
|
||||
- **Stack/Grid View**: `minmax(550px, 1fr)`. Guarantees wider columns. On a standard 1080p width (~1500px available), this results in **2 columns**. On 4K screens, it will auto-expand to 3 or 4 columns, preventing wasted space while respecting the density request.
|
||||
|
||||
## Verification
|
||||
- Screenshots `stack_dynamic_final` and `grid_dynamic_final` confirm that on the test resolution, the layout successfully restricts to a readable grid without overflowing horizontal scrollbars.
|
||||
@@ -1,12 +0,0 @@
|
||||
# Fix Socket.IO Payload Limit
|
||||
|
||||
## Issue
|
||||
The user reported a `413 (Payload Too Large)` error when creating a draft room with a full box of 36 packs. This was caused by the default `maxHttpBufferSize` limit (1MB) in Socket.IO, which is insufficient for the large JSON payload generated by 540 cards (36 packs * 15 cards) with full metadata.
|
||||
|
||||
## Resolution
|
||||
- Modified `src/server/index.ts` to increase `maxHttpBufferSize` to 300MB (3e8 bytes).
|
||||
- This explicitly sets the limit in the `Server` initialization options.
|
||||
|
||||
## Verification
|
||||
- `tsx watch` should automatically restart the server.
|
||||
- The new limit allows for massive payloads, covering the requirement for 36+ packs (requested >250MB).
|
||||
@@ -1,28 +0,0 @@
|
||||
# Basic Lands Handling
|
||||
|
||||
## Requirements
|
||||
- Upon draft room creation, basic lands from the selected sets must be cached and loaded.
|
||||
- During deck building, players must have access to an infinite number of these basic lands matching the selected sets.
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Server-Side
|
||||
- **Pack Generation**: Updated `/api/packs/generate` to extract unique basic lands from the processed card pool and return them in the response: `{ packs, basicLands }`.
|
||||
- **Room Management**: Updated `RoomManager` and `Room` interface to store `basicLands` array.
|
||||
- **Socket Events**: Updated `create_room` event handler to accept `basicLands` and pass them to the room creation logic.
|
||||
|
||||
### Client-Side
|
||||
- **State Management**: Added `availableLands` state to `App.tsx` with local storage persistence to persist lands between generation and lobby creation.
|
||||
- **Cube Manager**: Updated `handleGenerate` to parse the new API response and update specific state.
|
||||
- **Lobby Manager**:
|
||||
- Enhanced `handleCreateRoom` to include basic lands in the server-side image caching request.
|
||||
- Updated `create_room` socket emission to send the basic lands to the server.
|
||||
- **Deck Builder**:
|
||||
- Added a "Land Station" UI component.
|
||||
- If specific basic lands are available, it displays a horizontal scrollable gallery of the unique land arts.
|
||||
- Clicking a land adds a unique copy (with a specific ID) to the deck, allowing for infinite copies.
|
||||
- Preserved fallback to generic land counters if no specific lands are available.
|
||||
|
||||
## Verification
|
||||
- Verified flow from pack generation -> lobby -> room -> deck builder.
|
||||
- Validated that lands are deduplicated by Scryfall ID to ensure unique arts are offered.
|
||||
@@ -1,31 +0,0 @@
|
||||
# Land Advice and Unlimited Deck Building
|
||||
|
||||
## Requirements
|
||||
1. **Unlimited Timer**: The deck building phase should have an unlimited duration for now.
|
||||
2. **Land Advice Algorithm**:
|
||||
- Suggest a mana base aiming for a total of 17 lands (including those already picked in the deck).
|
||||
- Calculate the number of basic lands needed based on the color distribution (mana symbols) of the non-land cards in the deck.
|
||||
- Provide a UI to view and apply these suggestions.
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### `DeckBuilderView.tsx`
|
||||
|
||||
- **Timer disabled**: `useState<string>("Unlimited")` is used effectively to remove the countdown mechanism.
|
||||
- **Land Suggestion Algorithm**:
|
||||
- Target total lands: 17.
|
||||
- `existingLands` calculated from cards in `deck` with type `Land`.
|
||||
- `landsNeeded` = `max(0, 17 - existingLands)`.
|
||||
- Scans `mana_cost` of non-land cards to build a frequency map of colored mana symbols (`{W}`, `{U}`, etc.).
|
||||
- Distributes `landsNeeded` proportionally to the symbol counts.
|
||||
- Handles remainders by allocating them to the colors with the highest symbol counts.
|
||||
- Returns `null` if no colored symbols or `landsNeeded` is 0.
|
||||
- **UI**:
|
||||
- A panel "Land Advisor (Target: 17)" is added above the Land Station.
|
||||
- Displays the calculated basic land distribution (e.g., "P: 3, I: 2").
|
||||
- "Auto-Fill" button applies these counts to the `lands` state directly.
|
||||
|
||||
## Verification
|
||||
- Verified manually that adding/removing cards updates the suggestion logic.
|
||||
- "Unlimited" timer is displayed correctly.
|
||||
- Lint errors resolved.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user