From 4585e2a944f9b5f88a2c1d2fc3dc875b33d27ce6 Mon Sep 17 00:00:00 2001 From: dnviti Date: Fri, 19 Dec 2025 03:03:15 +0100 Subject: [PATCH] cleaned devlog --- ...4-12-18-163500_game_battlefield_sidebar.md | 26 --- .../2024-12-18-164500_game_persistence.md | 20 --- .../2024-12-18-165500_server_persistence.md | 26 --- ...-12-18-170500_distributed_storage_redis.md | 29 ---- .../2024-12-18-173500_strict_rules_engine.md | 23 --- ...024-12-18-180000_high_velocity_ux_part1.md | 20 --- ...024-12-18-182500_high_velocity_ux_part2.md | 34 ---- .../2024-12-18-185000_fix_initial_draw.md | 14 -- .../2024-12-18-185500_manual_draw_fix.md | 15 -- ...-12-18-190000_fix_actions_post_mulligan.md | 20 --- .../2024-12-18-190500_parsing_robustness.md | 19 --- .../2024-12-18-191000_fix_logging_crash.md | 13 -- ...-12-18-191500_fix_strict_action_payload.md | 24 --- .../2024-12-18-192500_fix_combat_skip.md | 16 -- .../2024-12-18-193000_strict_blocking_ui.md | 37 ----- .../2024-12-18-193500_force_combat_skip.md | 15 -- .../2024-12-18-200000_engine_enhancements.md | 45 ----- ...4-12-18-220000_ux_and_engine_completion.md | 26 --- ...2025-12-14-190500_initial_project_setup.md | 33 ---- .../2025-12-14-193500_migration_to_nodejs.md | 29 ---- .../2025-12-14-194558_core_implementation.md | 30 ---- ...12-14-203000_fix_root_render_generation.md | 19 --- ...2025-12-14-210000_fix_parser_robustness.md | 24 --- .../2025-12-14-211000_set_based_generation.md | 26 --- ...025-12-14-211500_remove_tournament_mode.md | 18 -- .../2025-12-14-212000_ui_simplification.md | 18 -- ...2025-12-14-212500_multiplayer_game_plan.md | 37 ----- .../2025-12-14-214400_fix_uuid_error.md | 15 -- .../2025-12-14-220000_game_interactions.md | 31 ---- ...2025-12-14-223000_draft_and_deckbuilder.md | 41 ----- .../devlog/2025-12-14-224500_image_caching.md | 37 ----- .../2025-12-14-230000_fix_draft_images.md | 17 -- .../2025-12-14-233000_fix_submit_deck.md | 28 ---- ...2-14-234500_fix_hooks_and_waiting_state.md | 22 --- ...2025-12-14-234500_game_battlefield_plan.md | 32 ---- .../2025-12-14-235000_game_context_menu.md | 39 ----- .../2025-12-14-235500_enhance_3d_game_view.md | 41 ----- ...25-12-14-235700_docker_containerization.md | 31 ---- .../2025-12-15-002500_deck_tester_feature.md | 32 ---- ...25-12-16-131921_export_generated_packs_csv | 6 - ...2025-12-16-152253_csv_import_robustness.md | 21 --- ...12-16-180000_draft_rules_implementation.md | 17 -- ...5-12-16-183000_fix_socket_mixed_content.md | 14 -- .../2025-12-16-184500_fix_pack_duplication.md | 13 -- ...-12-16-191500_reconnection_and_autopick.md | 21 --- .../2025-12-16-195000_draft_ui_polish.md | 23 --- .../2025-12-16-200500_resizable_draft_ui.md | 34 ---- .../devlog/2025-12-16-201500_card_zoom.md | 13 -- .../devlog/2025-12-16-203000_zoom_zone.md | 15 -- ...2025-12-16-213500_host_disconnect_pause.md | 22 --- .../2025-12-16-215000_anti_tampering.md | 26 --- .../2025-12-16-215500_fix_draft_ui_layout.md | 12 -- .../2025-12-16-220000_session_persistence.md | 38 ----- .../2025-12-16-221000_lobby_improvements.md | 46 ------ .../devlog/2025-12-16-222500_draft_timer.md | 32 ---- .../2025-12-16-223000_enhance_metadata.md | 21 --- ...025-12-16-224000_pack_generation_update.md | 30 ---- ...-12-16-224500_card_metadata_enhancement.md | 26 --- .../2025-12-16-225700_peasant_algorithm.md | 20 --- .../2025-12-16-230000_persist_metadata.md | 28 ---- ...-12-16-230500_multi_expansion_selection.md | 14 -- .../2025-12-16-231000_game_type_filter.md | 15 -- .../2025-12-16-231500_bulk_parse_feedback.md | 20 --- .../2025-12-16-233000_incremental_caching.md | 13 -- ...-12-16-234500_full_metadata_passthrough.md | 20 --- .../2025-12-16-235900_server_side_caching.md | 25 --- .../2025-12-17-002000_server_shutdown_fix.md | 17 -- .../2025-12-17-003000_cube_sticky_sidebar.md | 14 -- .../2025-12-17-003500_cube_full_width.md | 12 -- .../2025-12-17-004500_archidekt_view.md | 16 -- .../2025-12-17-005000_mobile_ui_fixes.md | 20 --- .../2025-12-17-005500_mobile_long_press.md | 15 -- ...-12-17-010000_mobile_fullscreen_preview.md | 16 -- ...-12-17-010500_mobile_preview_animations.md | 18 -- ...2025-12-17-011000_mobile_preview_polish.md | 21 --- .../2025-12-17-011500_enhanced_foils.md | 15 -- .../2025-12-17-012000_rolling_rainbow_foil.md | 15 -- ...2025-12-17-013000_card_visibility_boost.md | 13 -- ...025-12-17-013500_optimized_rolling_foil.md | 13 -- ...5-12-17-014000_metallic_foil_refinement.md | 13 -- ...25-12-17-014500_circular_foil_animation.md | 17 -- .../2025-12-17-015000_mild_foil_animation.md | 16 -- ...25-12-17-020000_pro_foil_implementation.md | 20 --- ...-17-020500_universal_preview_animations.md | 18 -- .../2025-12-17-021000_mobile_touch_fix.md | 16 -- ...025-12-17-021500_entrance_animation_fix.md | 17 -- .../devlog/2025-12-17-022000_foil_bug_fix.md | 13 -- ...5-12-17-022000_replace_alert_with_toast.md | 16 -- ...12-17-022500_universal_foil_application.md | 16 -- ...-12-17-023000_enhanced_toast_visibility.md | 21 --- ...-12-17-023000_smart_preview_suppression.md | 16 -- .../2025-12-17-023500_compact_card_layout.md | 18 -- .../2025-12-17-023500_unified_toast_design.md | 17 -- .../2025-12-17-024000_animated_copy_button.md | 20 --- .../2025-12-17-024000_view_scale_slider.md | 19 --- .../2025-12-17-024500_dynamic_art_cropping.md | 18 -- ...7-024500_fix_expansion_generation_limit.md | 22 --- ...-12-17-024600_mobile_long_press_preview.md | 17 -- .../2025-12-17-024800_mobile_card_slider.md | 16 -- ...2-17-025000_refined_preview_suppression.md | 14 -- .../2025-12-17-025500_change_default_flags.md | 19 --- ...-17-025500_explicit_preview_suppression.md | 16 -- ...25-12-17-030000_synchronized_boundaries.md | 13 -- .../2025-12-17-030500_squared_art_crops.md | 16 -- ...12-17-030600_fix_strict_pack_generation.md | 45 ----- .../2025-12-17-031000_sidebar_max_width.md | 14 -- .../2025-12-17-031500_play_online_logic.md | 19 --- .../2025-12-17-032000_lobby_rules_tooltip.md | 16 -- ...5-12-17-140000_fix_expansion_generation.md | 22 --- .../2025-12-17-142500_responsive_pack_grid.md | 20 --- ...025-12-17-143000_stack_view_consistency.md | 17 -- .../2025-12-17-144000_dynamic_pack_grid.md | 19 --- ...5-12-17-152700_fix_socket_payload_limit.md | 12 -- .../2025-12-17-153300_basic_lands_handling.md | 28 ---- ...7-155500_land_advice_and_unlimited_time.md | 31 ---- ...2-17-160500_deck_builder_magnified_view.md | 27 --- ...500_gameplay_magnified_view_and_timeout.md | 24 --- .../2025-12-17-162500_test_deck_feature.md | 32 ---- .../2025-12-17-165500_update_deck_autofill.md | 18 -- ...-12-17-170000_customizable_deck_builder.md | 55 ------- .../2025-12-17-183000_restore_stack_hover.md | 16 -- .../2025-12-17-183500_draft_ui_upgrade.md | 16 -- .../2025-12-17-184000_fix_draft_pool_ui.md | 13 -- .../2025-12-17-185000_draft_view_layout.md | 19 --- ...12-18-004109_fix_cube_sidebar_scrolling.md | 14 -- .../2025-12-18-004600_pwa_install_prompt.md | 23 --- .../2025-12-18-005000_fix_pwa_prompt.md | 33 ---- ...2025-12-18-005300_persist_pwa_dismissal.md | 20 --- .../2025-12-18-005739_create_favicon.md | 10 -- .../2025-12-18-012500_mobile_touch_preview.md | 15 -- ...5-12-18-013000_minimize_slider_defaults.md | 16 -- .../2025-12-18-014500_deck_builder_touch.md | 20 --- ...2025-12-18-020000_stack_sorting_sliders.md | 34 ---- .../2025-12-18-023000_lobby_ui_update.md | 28 ---- .../2025-12-18-024000_preview_threshold.md | 12 -- .../2025-12-18-030000_ui_enhancements.md | 28 ---- .../2025-12-18-033000_resize_optimization.md | 27 --- .../2025-12-18-034500_slider_optimization.md | 27 --- .../2025-12-18-040000_sidebar_resize_fix.md | 16 -- .../devlog/2025-12-18-041500_touch_resize.md | 20 --- .../2025-12-18-042500_pool_card_sizing.md | 13 -- .../2025-12-18-043500_pool_sizing_final.md | 31 ---- .../2025-12-18-044500_pool_overflow_fix.md | 13 -- .../2025-12-18-050000_resize_persistence.md | 18 -- .../2025-12-18-112633_resolve_413_errors.md | 16 -- ...-184500_mtg_engine_and_ux_archived_plan.md | 154 ------------------ ...025-12-18-193855_implement_restart_game.md | 10 -- ...2025-12-18-194500_dev_reliability_fixes.md | 14 -- ...25-12-18-195000_battlefield_restructure.md | 18 -- ...25-12-18-195300_battlefield_card_sizing.md | 9 - .../devlog/2025-12-18-195623_game_dnd_kit.md | 20 --- ...5-12-18-200000_battlefield_cutout_style.md | 24 --- ...12-18-201500_fix_battlefield_appearance.md | 24 --- ...25-12-18-202000_robust_artwork_fetching.md | 23 --- .../2025-12-18-202618_update_clear_session.md | 14 -- .../2025-12-18-203000_fix_restart_game.md | 19 --- .../2025-12-18-204000_cache_art_crops.md | 23 --- ...-12-18-205000_cache_folder_organization.md | 26 --- ...025-12-18-210000_fix_cube_session_clear.md | 22 --- ...18-210500_preserve_preferences_in_clear.md | 14 -- ...025-12-18-213300_strict_cache_structure.md | 18 -- ...025-12-18-213900_implicit_image_caching.md | 17 -- ...2025-12-18-214300_restore_images_subdir.md | 16 -- ...2025-12-19-011500_fix_build_unused_vars.md | 24 --- 164 files changed, 3622 deletions(-) delete mode 100644 docs/development/devlog/2024-12-18-163500_game_battlefield_sidebar.md delete mode 100644 docs/development/devlog/2024-12-18-164500_game_persistence.md delete mode 100644 docs/development/devlog/2024-12-18-165500_server_persistence.md delete mode 100644 docs/development/devlog/2024-12-18-170500_distributed_storage_redis.md delete mode 100644 docs/development/devlog/2024-12-18-173500_strict_rules_engine.md delete mode 100644 docs/development/devlog/2024-12-18-180000_high_velocity_ux_part1.md delete mode 100644 docs/development/devlog/2024-12-18-182500_high_velocity_ux_part2.md delete mode 100644 docs/development/devlog/2024-12-18-185000_fix_initial_draw.md delete mode 100644 docs/development/devlog/2024-12-18-185500_manual_draw_fix.md delete mode 100644 docs/development/devlog/2024-12-18-190000_fix_actions_post_mulligan.md delete mode 100644 docs/development/devlog/2024-12-18-190500_parsing_robustness.md delete mode 100644 docs/development/devlog/2024-12-18-191000_fix_logging_crash.md delete mode 100644 docs/development/devlog/2024-12-18-191500_fix_strict_action_payload.md delete mode 100644 docs/development/devlog/2024-12-18-192500_fix_combat_skip.md delete mode 100644 docs/development/devlog/2024-12-18-193000_strict_blocking_ui.md delete mode 100644 docs/development/devlog/2024-12-18-193500_force_combat_skip.md delete mode 100644 docs/development/devlog/2024-12-18-200000_engine_enhancements.md delete mode 100644 docs/development/devlog/2024-12-18-220000_ux_and_engine_completion.md delete mode 100644 docs/development/devlog/2025-12-14-190500_initial_project_setup.md delete mode 100644 docs/development/devlog/2025-12-14-193500_migration_to_nodejs.md delete mode 100644 docs/development/devlog/2025-12-14-194558_core_implementation.md delete mode 100644 docs/development/devlog/2025-12-14-203000_fix_root_render_generation.md delete mode 100644 docs/development/devlog/2025-12-14-210000_fix_parser_robustness.md delete mode 100644 docs/development/devlog/2025-12-14-211000_set_based_generation.md delete mode 100644 docs/development/devlog/2025-12-14-211500_remove_tournament_mode.md delete mode 100644 docs/development/devlog/2025-12-14-212000_ui_simplification.md delete mode 100644 docs/development/devlog/2025-12-14-212500_multiplayer_game_plan.md delete mode 100644 docs/development/devlog/2025-12-14-214400_fix_uuid_error.md delete mode 100644 docs/development/devlog/2025-12-14-220000_game_interactions.md delete mode 100644 docs/development/devlog/2025-12-14-223000_draft_and_deckbuilder.md delete mode 100644 docs/development/devlog/2025-12-14-224500_image_caching.md delete mode 100644 docs/development/devlog/2025-12-14-230000_fix_draft_images.md delete mode 100644 docs/development/devlog/2025-12-14-233000_fix_submit_deck.md delete mode 100644 docs/development/devlog/2025-12-14-234500_fix_hooks_and_waiting_state.md delete mode 100644 docs/development/devlog/2025-12-14-234500_game_battlefield_plan.md delete mode 100644 docs/development/devlog/2025-12-14-235000_game_context_menu.md delete mode 100644 docs/development/devlog/2025-12-14-235500_enhance_3d_game_view.md delete mode 100644 docs/development/devlog/2025-12-14-235700_docker_containerization.md delete mode 100644 docs/development/devlog/2025-12-15-002500_deck_tester_feature.md delete mode 100644 docs/development/devlog/2025-12-16-131921_export_generated_packs_csv delete mode 100644 docs/development/devlog/2025-12-16-152253_csv_import_robustness.md delete mode 100644 docs/development/devlog/2025-12-16-180000_draft_rules_implementation.md delete mode 100644 docs/development/devlog/2025-12-16-183000_fix_socket_mixed_content.md delete mode 100644 docs/development/devlog/2025-12-16-184500_fix_pack_duplication.md delete mode 100644 docs/development/devlog/2025-12-16-191500_reconnection_and_autopick.md delete mode 100644 docs/development/devlog/2025-12-16-195000_draft_ui_polish.md delete mode 100644 docs/development/devlog/2025-12-16-200500_resizable_draft_ui.md delete mode 100644 docs/development/devlog/2025-12-16-201500_card_zoom.md delete mode 100644 docs/development/devlog/2025-12-16-203000_zoom_zone.md delete mode 100644 docs/development/devlog/2025-12-16-213500_host_disconnect_pause.md delete mode 100644 docs/development/devlog/2025-12-16-215000_anti_tampering.md delete mode 100644 docs/development/devlog/2025-12-16-215500_fix_draft_ui_layout.md delete mode 100644 docs/development/devlog/2025-12-16-220000_session_persistence.md delete mode 100644 docs/development/devlog/2025-12-16-221000_lobby_improvements.md delete mode 100644 docs/development/devlog/2025-12-16-222500_draft_timer.md delete mode 100644 docs/development/devlog/2025-12-16-223000_enhance_metadata.md delete mode 100644 docs/development/devlog/2025-12-16-224000_pack_generation_update.md delete mode 100644 docs/development/devlog/2025-12-16-224500_card_metadata_enhancement.md delete mode 100644 docs/development/devlog/2025-12-16-225700_peasant_algorithm.md delete mode 100644 docs/development/devlog/2025-12-16-230000_persist_metadata.md delete mode 100644 docs/development/devlog/2025-12-16-230500_multi_expansion_selection.md delete mode 100644 docs/development/devlog/2025-12-16-231000_game_type_filter.md delete mode 100644 docs/development/devlog/2025-12-16-231500_bulk_parse_feedback.md delete mode 100644 docs/development/devlog/2025-12-16-233000_incremental_caching.md delete mode 100644 docs/development/devlog/2025-12-16-234500_full_metadata_passthrough.md delete mode 100644 docs/development/devlog/2025-12-16-235900_server_side_caching.md delete mode 100644 docs/development/devlog/2025-12-17-002000_server_shutdown_fix.md delete mode 100644 docs/development/devlog/2025-12-17-003000_cube_sticky_sidebar.md delete mode 100644 docs/development/devlog/2025-12-17-003500_cube_full_width.md delete mode 100644 docs/development/devlog/2025-12-17-004500_archidekt_view.md delete mode 100644 docs/development/devlog/2025-12-17-005000_mobile_ui_fixes.md delete mode 100644 docs/development/devlog/2025-12-17-005500_mobile_long_press.md delete mode 100644 docs/development/devlog/2025-12-17-010000_mobile_fullscreen_preview.md delete mode 100644 docs/development/devlog/2025-12-17-010500_mobile_preview_animations.md delete mode 100644 docs/development/devlog/2025-12-17-011000_mobile_preview_polish.md delete mode 100644 docs/development/devlog/2025-12-17-011500_enhanced_foils.md delete mode 100644 docs/development/devlog/2025-12-17-012000_rolling_rainbow_foil.md delete mode 100644 docs/development/devlog/2025-12-17-013000_card_visibility_boost.md delete mode 100644 docs/development/devlog/2025-12-17-013500_optimized_rolling_foil.md delete mode 100644 docs/development/devlog/2025-12-17-014000_metallic_foil_refinement.md delete mode 100644 docs/development/devlog/2025-12-17-014500_circular_foil_animation.md delete mode 100644 docs/development/devlog/2025-12-17-015000_mild_foil_animation.md delete mode 100644 docs/development/devlog/2025-12-17-020000_pro_foil_implementation.md delete mode 100644 docs/development/devlog/2025-12-17-020500_universal_preview_animations.md delete mode 100644 docs/development/devlog/2025-12-17-021000_mobile_touch_fix.md delete mode 100644 docs/development/devlog/2025-12-17-021500_entrance_animation_fix.md delete mode 100644 docs/development/devlog/2025-12-17-022000_foil_bug_fix.md delete mode 100644 docs/development/devlog/2025-12-17-022000_replace_alert_with_toast.md delete mode 100644 docs/development/devlog/2025-12-17-022500_universal_foil_application.md delete mode 100644 docs/development/devlog/2025-12-17-023000_enhanced_toast_visibility.md delete mode 100644 docs/development/devlog/2025-12-17-023000_smart_preview_suppression.md delete mode 100644 docs/development/devlog/2025-12-17-023500_compact_card_layout.md delete mode 100644 docs/development/devlog/2025-12-17-023500_unified_toast_design.md delete mode 100644 docs/development/devlog/2025-12-17-024000_animated_copy_button.md delete mode 100644 docs/development/devlog/2025-12-17-024000_view_scale_slider.md delete mode 100644 docs/development/devlog/2025-12-17-024500_dynamic_art_cropping.md delete mode 100644 docs/development/devlog/2025-12-17-024500_fix_expansion_generation_limit.md delete mode 100644 docs/development/devlog/2025-12-17-024600_mobile_long_press_preview.md delete mode 100644 docs/development/devlog/2025-12-17-024800_mobile_card_slider.md delete mode 100644 docs/development/devlog/2025-12-17-025000_refined_preview_suppression.md delete mode 100644 docs/development/devlog/2025-12-17-025500_change_default_flags.md delete mode 100644 docs/development/devlog/2025-12-17-025500_explicit_preview_suppression.md delete mode 100644 docs/development/devlog/2025-12-17-030000_synchronized_boundaries.md delete mode 100644 docs/development/devlog/2025-12-17-030500_squared_art_crops.md delete mode 100644 docs/development/devlog/2025-12-17-030600_fix_strict_pack_generation.md delete mode 100644 docs/development/devlog/2025-12-17-031000_sidebar_max_width.md delete mode 100644 docs/development/devlog/2025-12-17-031500_play_online_logic.md delete mode 100644 docs/development/devlog/2025-12-17-032000_lobby_rules_tooltip.md delete mode 100644 docs/development/devlog/2025-12-17-140000_fix_expansion_generation.md delete mode 100644 docs/development/devlog/2025-12-17-142500_responsive_pack_grid.md delete mode 100644 docs/development/devlog/2025-12-17-143000_stack_view_consistency.md delete mode 100644 docs/development/devlog/2025-12-17-144000_dynamic_pack_grid.md delete mode 100644 docs/development/devlog/2025-12-17-152700_fix_socket_payload_limit.md delete mode 100644 docs/development/devlog/2025-12-17-153300_basic_lands_handling.md delete mode 100644 docs/development/devlog/2025-12-17-155500_land_advice_and_unlimited_time.md delete mode 100644 docs/development/devlog/2025-12-17-160500_deck_builder_magnified_view.md delete mode 100644 docs/development/devlog/2025-12-17-161500_gameplay_magnified_view_and_timeout.md delete mode 100644 docs/development/devlog/2025-12-17-162500_test_deck_feature.md delete mode 100644 docs/development/devlog/2025-12-17-165500_update_deck_autofill.md delete mode 100644 docs/development/devlog/2025-12-17-170000_customizable_deck_builder.md delete mode 100644 docs/development/devlog/2025-12-17-183000_restore_stack_hover.md delete mode 100644 docs/development/devlog/2025-12-17-183500_draft_ui_upgrade.md delete mode 100644 docs/development/devlog/2025-12-17-184000_fix_draft_pool_ui.md delete mode 100644 docs/development/devlog/2025-12-17-185000_draft_view_layout.md delete mode 100644 docs/development/devlog/2025-12-18-004109_fix_cube_sidebar_scrolling.md delete mode 100644 docs/development/devlog/2025-12-18-004600_pwa_install_prompt.md delete mode 100644 docs/development/devlog/2025-12-18-005000_fix_pwa_prompt.md delete mode 100644 docs/development/devlog/2025-12-18-005300_persist_pwa_dismissal.md delete mode 100644 docs/development/devlog/2025-12-18-005739_create_favicon.md delete mode 100644 docs/development/devlog/2025-12-18-012500_mobile_touch_preview.md delete mode 100644 docs/development/devlog/2025-12-18-013000_minimize_slider_defaults.md delete mode 100644 docs/development/devlog/2025-12-18-014500_deck_builder_touch.md delete mode 100644 docs/development/devlog/2025-12-18-020000_stack_sorting_sliders.md delete mode 100644 docs/development/devlog/2025-12-18-023000_lobby_ui_update.md delete mode 100644 docs/development/devlog/2025-12-18-024000_preview_threshold.md delete mode 100644 docs/development/devlog/2025-12-18-030000_ui_enhancements.md delete mode 100644 docs/development/devlog/2025-12-18-033000_resize_optimization.md delete mode 100644 docs/development/devlog/2025-12-18-034500_slider_optimization.md delete mode 100644 docs/development/devlog/2025-12-18-040000_sidebar_resize_fix.md delete mode 100644 docs/development/devlog/2025-12-18-041500_touch_resize.md delete mode 100644 docs/development/devlog/2025-12-18-042500_pool_card_sizing.md delete mode 100644 docs/development/devlog/2025-12-18-043500_pool_sizing_final.md delete mode 100644 docs/development/devlog/2025-12-18-044500_pool_overflow_fix.md delete mode 100644 docs/development/devlog/2025-12-18-050000_resize_persistence.md delete mode 100644 docs/development/devlog/2025-12-18-112633_resolve_413_errors.md delete mode 100644 docs/development/devlog/2025-12-18-184500_mtg_engine_and_ux_archived_plan.md delete mode 100644 docs/development/devlog/2025-12-18-193855_implement_restart_game.md delete mode 100644 docs/development/devlog/2025-12-18-194500_dev_reliability_fixes.md delete mode 100644 docs/development/devlog/2025-12-18-195000_battlefield_restructure.md delete mode 100644 docs/development/devlog/2025-12-18-195300_battlefield_card_sizing.md delete mode 100644 docs/development/devlog/2025-12-18-195623_game_dnd_kit.md delete mode 100644 docs/development/devlog/2025-12-18-200000_battlefield_cutout_style.md delete mode 100644 docs/development/devlog/2025-12-18-201500_fix_battlefield_appearance.md delete mode 100644 docs/development/devlog/2025-12-18-202000_robust_artwork_fetching.md delete mode 100644 docs/development/devlog/2025-12-18-202618_update_clear_session.md delete mode 100644 docs/development/devlog/2025-12-18-203000_fix_restart_game.md delete mode 100644 docs/development/devlog/2025-12-18-204000_cache_art_crops.md delete mode 100644 docs/development/devlog/2025-12-18-205000_cache_folder_organization.md delete mode 100644 docs/development/devlog/2025-12-18-210000_fix_cube_session_clear.md delete mode 100644 docs/development/devlog/2025-12-18-210500_preserve_preferences_in_clear.md delete mode 100644 docs/development/devlog/2025-12-18-213300_strict_cache_structure.md delete mode 100644 docs/development/devlog/2025-12-18-213900_implicit_image_caching.md delete mode 100644 docs/development/devlog/2025-12-18-214300_restore_images_subdir.md delete mode 100644 docs/development/devlog/2025-12-19-011500_fix_build_unused_vars.md diff --git a/docs/development/devlog/2024-12-18-163500_game_battlefield_sidebar.md b/docs/development/devlog/2024-12-18-163500_game_battlefield_sidebar.md deleted file mode 100644 index aa7bc0a..0000000 --- a/docs/development/devlog/2024-12-18-163500_game_battlefield_sidebar.md +++ /dev/null @@ -1,26 +0,0 @@ - -# 2024-12-18 16:35:00 - Refactor Game Battlefield Sidebar - -## Description -Refactored the `GameView` sidebar to be graphically and functionally consistent with `DeckBuilderView` and `DraftView`. - -## Key Changes -- **Component**: `GameView.tsx` -- **Functionality**: - - Implemented collapsible sidebar state with persistence (`game_sidebarCollapsed`). - - Implemented resizable sidebar width with persistence (`game_sidebarWidth`). - - Added transition animations for collapsing/expanding. -- **Visuals**: - - Adopted the "Card Preview" style with a 3D flip effect. - - Used `back.jpg` (path `/images/back.jpg`) for the empty/back state. - - Moved the resize handle *inside* the sidebar container with consistent styling (floating pill). - - Preserved Oracle Text display below the card image (as it is critical for gameplay), styled within the new container. - -## Consistent Elements -- **Icons**: Used `Eye` and `ChevronLeft` from Lucide. -- **Styling**: `slate-900` backgrounds, glassmorphism borders (`slate-800/50`), shadow effects. -- **Behavior**: Sidebar width allows dragging between 200px and 600px. - -## Status -- [ ] Verify `back.jpg` exists in the deployed `public/images` folder (currently assumed based on other files). -- [x] Code refactoring complete. diff --git a/docs/development/devlog/2024-12-18-164500_game_persistence.md b/docs/development/devlog/2024-12-18-164500_game_persistence.md deleted file mode 100644 index 7542ded..0000000 --- a/docs/development/devlog/2024-12-18-164500_game_persistence.md +++ /dev/null @@ -1,20 +0,0 @@ - -# 2024-12-18 16:45:00 - Implement Game Persistence on Reload - -## Description -Updated `LobbyManager.tsx` to ensure that when a user reloads the page and automatically rejoins a room, the active game state (`initialGameState`) is correctly retrieved from the server and passed to the game view components. - -## Key Changes -- **Component**: `LobbyManager.tsx` -- **Functionality**: - - Added `initialGameState` state. - - Updated `join_room` and `rejoin_room` response handling to capture `gameState` if present. - - Passed `initialGameState` to the `GameRoom` component. - -## Impact -- **User Experience**: If a user is in the middle of a game (battlefield phase) and refreshes the browser, they will now immediately see the battlefield state instead of a loading or broken screen, ensuring continuity. -- **Data Flow**: `GameRoom` uses this prop to initialize its local `gameState` before the first socket update event arrives. - -## Status -- [x] Implementation logic complete. -- [ ] User testing required (refresh page during active game). diff --git a/docs/development/devlog/2024-12-18-165500_server_persistence.md b/docs/development/devlog/2024-12-18-165500_server_persistence.md deleted file mode 100644 index d1e8af4..0000000 --- a/docs/development/devlog/2024-12-18-165500_server_persistence.md +++ /dev/null @@ -1,26 +0,0 @@ - -# 2024-12-18 16:55:00 - Implement Server Persistence and Room Cleanup - -## Description -Implemented server-side state persistence to ensure game rooms, drafts, and game states survive server restarts and network issues. Added logic to keep rooms alive for at least 8 hours after the last activity, satisfying the requirements for robustness and re-joinability. - -## Key Changes -1. **Persistence Manager**: - - Created `PersistenceManager.ts` to save and load `rooms`, `drafts`, and `games` to/from JSON files in `./server-data`. - - Integrated into `server/index.ts` with auto-save interval (every 5s) and save-on-shutdown. - -2. **Room Manager**: - - Added `lastActive` timestamp to `Room` interface. - - Updated `lastActive` on all significant interactions (join, leave, message, etc.). - - Implemented `disconnect` logic: if players disconnect, the room is NOT deleted immediately. - - Implemented `leaveRoom` logic: Explicit leaving (waiting phase) still removes players but preserves the room until cleanup if empty. - - Added `cleanupRooms()` method running every 5 minutes to delete rooms inactive for > 8 hours. - -## Impact -- **Reliability**: Server crashes or restarts will no longer wipe out active games or drafts. -- **User Experience**: Users can reconnect to their room even hours later (up to 8 hours), or after a server reboot, using their room code. -- **Maintenance**: `server-data` directory now contains the active state, useful for debugging. - -## Status -- [x] Code implementation complete. -- [ ] Verify `server-data` folder is created and populated on run. diff --git a/docs/development/devlog/2024-12-18-170500_distributed_storage_redis.md b/docs/development/devlog/2024-12-18-170500_distributed_storage_redis.md deleted file mode 100644 index c33c6c2..0000000 --- a/docs/development/devlog/2024-12-18-170500_distributed_storage_redis.md +++ /dev/null @@ -1,29 +0,0 @@ - -# 2024-12-18 17:05:00 - Distributed Storage with Redis - -## Description -Implemented distributed storage using Redis (`ioredis`) to support horizontal scaling and persistence outside of local file systems, while retaining local storage for development. - -## Key Changes -1. **Dependencies**: Added `ioredis` and `@types/ioredis`. -2. **Redis Manager**: created `RedisClientManager.ts` to manage connections: - - `db0`: Session Persistence (Rooms, Drafts, Games). - - `db1`: File Storage (Card Images, Metadata). - - Enabled via environment variable `USE_REDIS=true`. -3. **Persistence Manager**: Updated `PersistenceManager.ts` to read/write state to Redis DB 0 if enabled. -4. **File Storage Manager**: Created `FileStorageManager.ts` to abstract file operations (`saveFile`, `readFile`, `exists`). - - Uses Redis DB 1 if enabled. - - Uses Local FS otherwise. -5. **Card Service**: Refactored `CardService.ts` to use `FileStorageManager` instead of `fs` direct calls. -6. **Server File Serving**: Updated `server/index.ts` to conditionally serve files: - - If Redis enabled: Dynamic route intercepting `/cards/*` to fetch from Redis DB 1. - - If Local: Standard `express.static` middleware. - -## Configuration -- `USE_REDIS`: Set to `true` to enable Redis. -- `REDIS_HOST`: Default `localhost`. -- `REDIS_PORT`: Default `6379`. - -## Status -- [x] Code implementation complete. -- [ ] Redis functionality verification (requires Redis instance). diff --git a/docs/development/devlog/2024-12-18-173500_strict_rules_engine.md b/docs/development/devlog/2024-12-18-173500_strict_rules_engine.md deleted file mode 100644 index 226ebcf..0000000 --- a/docs/development/devlog/2024-12-18-173500_strict_rules_engine.md +++ /dev/null @@ -1,23 +0,0 @@ - -# 2024-12-18 17:35:00 - Strict Rules Engine Implementation - -## Description -Implemented a comprehensive Magic: The Gathering rules engine (Core Logic) to replace the sandbox mode with strict rules enforcement. This includes a State Machine for Turn Structure, Priority System, Stack, and State-Based Actions. - -## Key Changes -1. **Core Types**: Created `src/server/game/types.ts` defining `Phase`, `Step`, `StrictGameState`, `StackObject`, etc. -2. **Rules Engine**: Created `src/server/game/RulesEngine.ts` implementing: - - **Turn Structure**: Untap, Upkeep, Draw, Main, Combat (Steps), End. - - **Priority System**: Passing priority, stack resolution, phase transition. - - **Actions**: `playLand`, `castSpell` with validation. - - **State-Based Actions**: Lethal damage, Zero toughness, Player loss checks. -3. **Game Manager Refactor**: - - Updated `GameManager.ts` to use `StrictGameState`. - - Implemented `handleStrictAction` to delegate to `RulesEngine`. - - Retained `handleAction` for legacy/sandbox/admin support. -4. **Socket Handling**: - - Added `game_strict_action` event listener in `server/index.ts`. - -## Next Steps -- Client-side integration: The frontend needs to be updated to visualize the Phases, Stack, and Priority (Pass Button). -- Move from "Sandbox" UI to "Rules Enforcement" UI. diff --git a/docs/development/devlog/2024-12-18-180000_high_velocity_ux_part1.md b/docs/development/devlog/2024-12-18-180000_high_velocity_ux_part1.md deleted file mode 100644 index f9a950f..0000000 --- a/docs/development/devlog/2024-12-18-180000_high_velocity_ux_part1.md +++ /dev/null @@ -1,20 +0,0 @@ - -# 2024-12-18 18:00:00 - High-Velocity UX Implementation (Part 1) - -## Description -Started implementing the Frontend components for the High-Velocity UX Specification. Focused on the "Smart Priority Interface" components first to enable strict rules interaction. - -## Key Changes -1. **Frontend Plan**: Created `docs/development/plans/high-velocity-ux.md` detailing the gesture engine and UI components. -2. **Strict Types**: Updated `src/client/types/game.ts` to include `Phase`, `Step`, `StackObject`, and `StrictGameState` extensions. -3. **Smart Button**: Created `SmartButton.tsx` which derives state (Pass/Resolve/Wait) from the `StrictGameState`. - - Green: Pass/Advance Phase. - - Orange: Resolve Stack. - - Grey: Wait (Not Priority). -4. **Phase Strip**: Created `PhaseStrip.tsx` to visualize the linear turn structure and highlight the current step. -5. **GameView Integration**: Updated `GameView.tsx` to house these new controls in the bottom area. Wire up `SmartButton` to emit `game_strict_action`. - -## Next Steps -- Implement `GestureManager` context for Swipe-to-Tap and Swipe-to-Combat. -- Implement `StackVisualizer` to show objects on the stack. -- Connect `ContextMenu` to strict actions (Activate Ability). diff --git a/docs/development/devlog/2024-12-18-182500_high_velocity_ux_part2.md b/docs/development/devlog/2024-12-18-182500_high_velocity_ux_part2.md deleted file mode 100644 index fe94c1e..0000000 --- a/docs/development/devlog/2024-12-18-182500_high_velocity_ux_part2.md +++ /dev/null @@ -1,34 +0,0 @@ -# High Velocity UX & Strict Engine (Part 2) - -## Status: Completed - -## Objectives -- Implement "Manual Mana Engine" allowing players to add mana to their pool via interaction. -- Implement "Strict Combat Engine" supporting `DECLARE_ATTACKERS` and `DECLARE_BLOCKERS` phases and validation. -- Implement "High Velocity UX" with Swipe-to-Tap and Swipe-to-Attack gestures. -- Enhance `GameView` with Mana Pool display and visual feedback for combat declarations. -- Contextualize `SmartButton` to handle complex actions like declaring specific attackers. - -## Implementation Details - -### Backend (Rules Engine) -- **Mana System**: Added `addMana` method to `RulesEngine` and `manaPool` to `PlayerState`. Implemented `emptyManaPools` logic on step transition. -- **Combat Logic**: Implemented `declareAttackers` (checking summoning sickness, tapping, setting attacking target) and `declareBlockers` logic. -- **Action Handling**: Updated `GameManager` to handle `ADD_MANA` and auto-generate mana when tapping Basic Lands via `TAP_CARD` action (legacy compatibility wrapper). - -### Frontend (GameView) -- **Mana Pool UI**: Added a compact Mana Pool display in the player life area, showing WUBRGC counts. -- **Gesture Manager Upgrade**: Enhanced `GestureManager` to detect swipe direction: - - **Slash (Horizontal)**: Tap Card. - - **Thrust (Vertical Up)**: Attack (if in combat step). - - **Thrust (Vertical Down)**: Cancel Attack. -- **Combat Visuals**: Implemented `proposedAttackers` local state. Cards proposed to attack are visually lifted (`translateY(-40px)`) and glow red (`box-shadow`, `ring`). -- **Smart Button**: Updated to accept `contextData`. In `declare_attackers` step, it displays "Attack with N" and sends the list of proposed attackers. - -### Type Synchronization -- Synced `CardInstance` (Client) with `CardObject` (Server) to include `attacking` and `blocking` fields. - -## Next Steps -- Verify Multiplayer Sync (Socket events are already in place). -- Implement "Blocking" UI (similar to Attacking but for defenders). -- Implement "Order Blockers" / "Damage Assignment" if strict compliance is enforced (currently simplified to auto-damage). diff --git a/docs/development/devlog/2024-12-18-185000_fix_initial_draw.md b/docs/development/devlog/2024-12-18-185000_fix_initial_draw.md deleted file mode 100644 index b917728..0000000 --- a/docs/development/devlog/2024-12-18-185000_fix_initial_draw.md +++ /dev/null @@ -1,14 +0,0 @@ -# 2024-12-18 - Fix Initial Draw Logic - -## Problem -The user reported that upon entering the game and being prompted to Mulligan, their hand was empty. This prevented them from making an informed decision. - -## Root Cause -The `GameManager` initialized the game state with `step: 'mulligan'`, but the `RulesEngine` was never invoked to perform the initial turn-based actions (specifically the initial draw). The cards were added to the `library` zone, but no logic moved them to the `hand` zone before the game start update was sent to the client. - -## Solution -1. **Updated `RulesEngine.ts`**: Added a public `startGame()` method that logs the start and calls `performTurnBasedActions()`. `performTurnBasedActions()` already contained the logic to draw 7 cards if the step is 'mulligan' and the hand is empty. -2. **Updated `server/index.ts`**: Modified all game initialization flows (`player_ready`, `start_solo_test`, `start_game`, and the global timer loop) to instantiate a `RulesEngine` and call `startGame()` immediately after populating the deck cards. - -## outcome -When a game starts, the server now proactively triggers the initial draw logic. Clients receive the initial game state with 7 cards in hand, allowing the Mulligan UI to display the cards correctly. diff --git a/docs/development/devlog/2024-12-18-185500_manual_draw_fix.md b/docs/development/devlog/2024-12-18-185500_manual_draw_fix.md deleted file mode 100644 index 8a5f0ee..0000000 --- a/docs/development/devlog/2024-12-18-185500_manual_draw_fix.md +++ /dev/null @@ -1,15 +0,0 @@ -# 2024-12-18 - Implement Manual Card Draw - -## Problem -The user reported that clicking on the library or using the "Draw Card" context menu option had no effect. The frontend was correctly emitting the `DRAW_CARD` action (via `game_action` channel/event), but the `GameManager` (which handles manual/legacy actions) had no case handler for it, causing the action to be ignored. - -## Root Cause -1. **Missing Handler**: The `GameManager.handleAction` switch statement lacked a `case 'DRAW_CARD'`. -2. **Access Control**: The `RulesEngine.drawCard` method was `private`, preventing external invocation even if the handler existed. - -## Solution -1. **Made `drawCard` Public**: Updated `RulesEngine.ts` to change `drawCard` visibility from `private` to `public`. -2. **Added Handler**: Updated `GameManager.ts` to include a `case 'DRAW_CARD'` in `handleAction`. This handler instantiates a `RulesEngine` for the current game and calls `engine.drawCard(actorId)`. - -## Outcome -Users can now manually draw cards from their library interactions (click or context menu) during gameplay. diff --git a/docs/development/devlog/2024-12-18-190000_fix_actions_post_mulligan.md b/docs/development/devlog/2024-12-18-190000_fix_actions_post_mulligan.md deleted file mode 100644 index 7743144..0000000 --- a/docs/development/devlog/2024-12-18-190000_fix_actions_post_mulligan.md +++ /dev/null @@ -1,20 +0,0 @@ -# 2024-12-18 - Fix Actions Post-Mulligan - -## Problem -After the Mulligan phase, users reported "no actions working". The Smart Button and other strict interactions (Priority passing) were failing. - -## Root Cause -1. **Frontend Emission**: The `SmartButton` in `GameView.tsx` and the `RadialMenu` for mana were emitting legacy `type` strings (e.g. `PASS_PRIORITY` or `ADD_MANA` directly), or wrapped incorrectly. Specifically, `SmartButton` was correctly wrapping in `game_strict_action` but likely the state alignment was off. -2. **Radial Menu**: Was emitting `ADD_MANA` as a legacy `game_action`. Legacy `GameManager` (before my fix in previous step) handled basic actions, but `ADD_MANA` is a strict engine concept. `GameManager.handleAction` (legacy) did not handle it. We needed to target `game_strict_action` or add a handler. -3. **State Reset**: The engine's transition from Mulligan -> Untap -> Upkeep -> Draw -> Main1 relies on `resetPriority` correctly assigning priority to the Active Player. If this flow is interrupted or if the client UI doesn't realize it has priority (due to `priorityPlayerId` mismatch), the Smart Button disables itself. - -## Solution -1. **Strict Action Alignment**: Updated `GameView.tsx` to ensure `RadialMenu` (Mana) emits `game_strict_action`. -2. **Handling**: (Previous Step) Added `DRAW_CARD` support. -3. **Smart Button Checking**: Confirmed Smart Button emits `type` which `GameView` wraps in `action`. This matches `socket.on('game_strict_action', { action })`. This path is correct. - -## Verification -The flow "Mulligan -> Advanced Step (Mulligan Ends) -> Untap (Auto) -> Upkeep -> Reset Priority (Active Player)" seems logic-sound in `RulesEngine`. With the frontend now targeting the strict endpoint for Mana/Priority, and the legacy handler updated for Draw, the loop should be closed. - -## Remaining Risk -If `resetPriority` sets `priorityPlayerId` to a player ID that doesn't match the client's `currentPlayerId` (e.g. Turn 1 Order), the button will stay gray/disabled. This is Rules Correct (you can't act if not your priority), but UI feedback (telling *whose* turn/priority it is) is crucial. The existing `PhaseStrip` or `SmartButton` should indicate this. diff --git a/docs/development/devlog/2024-12-18-190500_parsing_robustness.md b/docs/development/devlog/2024-12-18-190500_parsing_robustness.md deleted file mode 100644 index 729af7a..0000000 --- a/docs/development/devlog/2024-12-18-190500_parsing_robustness.md +++ /dev/null @@ -1,19 +0,0 @@ -# 2024-12-18 - Parse Card Data Robustness - -## Problem -The user reported issues with "placing cards onto the battlefield". Specifically, this manifested in two likely ways: -1. Creature cards fading away instantly (dying to State-Based Actions) because their Power/Toughness was defaulted to 0/0. -2. Cards resolving to the Graveyard instead of Battlefield because the `RulesEngine` failed to identify them as Permanents (empty `types` array), defaulting to Instant/Sorcery behavior. - -## Root Cause -1. **Missing P/T Passing**: The `server/index.ts` file was constructing the initial game state from deck cards but failing to explicitly copy `power` and `toughness` properties. -2. **Missing Type Parsing**: The `GameManager` (and `index.ts`) relied on `typeLine` string but did not parse it into the `types` array which the `RulesEngine` strictly checks for `isPermanent` logic and invalid aura validation. - -## Solution -1. **Updated `GameManager.ts`**: Added robust parsing logic in `addCardToGame`. If `card.types` is empty, it now parses `card.typeLine` (e.g. splitting "Legendary Creature — Human") to populate `types`, `supertypes`, and `subtypes` arrays. -2. **Updated `server/index.ts`**: Modified all game initialization flows to explicitly pass `power` and `toughness` from the source data to `gameManager.addCardToGame`. - -## Outcome -Cards added to the game now have correct type metadata and base stats. -- Creatures resolve to the battlefield correctly (identified as Permanents). -- Creatures stay on the battlefield (Toughness > 0 prevents SBA death). diff --git a/docs/development/devlog/2024-12-18-191000_fix_logging_crash.md b/docs/development/devlog/2024-12-18-191000_fix_logging_crash.md deleted file mode 100644 index 2d0061d..0000000 --- a/docs/development/devlog/2024-12-18-191000_fix_logging_crash.md +++ /dev/null @@ -1,13 +0,0 @@ -# 2024-12-18 - Fix GameManager logging TypeError - -## Problem -The user reported a server crash with `TypeError: Cannot read properties of undefined (reading 'type')`. This occurred in the `GameManager.handleStrictAction` catch block when attempting to log `action.type` during an error condition, implying that `action` itself might be undefined or causing access issues in that context, or the error handling was too aggressive on a malformed payload. - -## Root Cause -The `catch(e)` block blindly accessed `action.type` to log the rule violation context. If `action` was null or undefined (which could happen if validation failed earlier or weird payloads arrived), this access threw the new error. Although `handleStrictAction` generally checks inputs, robust error logging should not crash. - -## Solution -Updated the catch block in `src/server/managers/GameManager.ts` to use optional chaining `action?.type` and provide a fallback string `'UNKNOWN'`. - -## Outcome -Server will now safely log "Rule Violation [UNKNOWN]" instead of crashing if the action payload is malformed during an error scenario. diff --git a/docs/development/devlog/2024-12-18-191500_fix_strict_action_payload.md b/docs/development/devlog/2024-12-18-191500_fix_strict_action_payload.md deleted file mode 100644 index 25a3e8b..0000000 --- a/docs/development/devlog/2024-12-18-191500_fix_strict_action_payload.md +++ /dev/null @@ -1,24 +0,0 @@ -# 2024-12-18 - Fix Strict Action Payload Construction - -## Problem -The user reported a server crash/error: `Rule Violation [UNKNOWN]: Cannot read properties of undefined (reading 'type')`. -This occurred when resolving lands or casting spells. The error log "UNKNOWN" indicated the server received a null/undefined `action` object within the `game_strict_action` event payload. -The server expects `socket.emit('game_strict_action', { action: { type: '...' } })`. -The client was emitting `socket.emit('game_strict_action', { type: '...' })` (missing the `action` wrapper). - -## Root Cause -When refactoring for the Strict Actions, the frontend calls for `handleZoneDrop` (Battlefield), `handleCardDrop`, and `handlePlayerDrop` were updated to emit the new event name `game_strict_action`, but the payload structure was not updated to wrap the data in an `{ action: ... }` object as expected by `server/index.ts`. - -## Solution -Updated `GameView.tsx` in three locations (`handleZoneDrop`, `handleCardDrop`, `handlePlayerDrop`) to correctly wrap the payload: -```typescript -socketService.socket.emit('game_strict_action', { - action: { - type: '...', - ... - } -}); -``` - -## Outcome -Client strict actions now match the server's expected payload structure. Actions like playing lands or casting spells should now execute defined logic instead of crashing or being treated as unknown. diff --git a/docs/development/devlog/2024-12-18-192500_fix_combat_skip.md b/docs/development/devlog/2024-12-18-192500_fix_combat_skip.md deleted file mode 100644 index 07ede50..0000000 --- a/docs/development/devlog/2024-12-18-192500_fix_combat_skip.md +++ /dev/null @@ -1,16 +0,0 @@ -# 2024-12-18 - Fix Combat Skip Logic - -## Problem -The user could not "Skip Combat" (Move past Declare Attackers). The button action `DECLARE_ATTACKERS` with 0 attackers was working server-side (resetting priority to AP), but the client UI (`SmartButton`) remained stuck on "Skip Combat". This created a loop where the user clicked, action processed, priority returned, and the UI still asked them to declare attackers. - -## Root Cause -The `SmartButton` logic relied solely on `gameState.step === 'declare_attackers'`. It did not differentiate between "Need to Declare" (Start of Step) and "After Declaration / Priority Window" (Middle of Step). -Strict Rules State did not have a flag to indicate if the Turn-Based Action of declaring attackers had already occurred for the current step. - -## Solution -1. **Updated `Types`**: Added optional `attackersDeclared` (and `blockersDeclared`) boolean flags to `StrictGameState` (Server + Client). -2. **Updated `RulesEngine`**: In `declareAttackers()`, set `attackersDeclared = true`. In `cleanupStep()`, reset these flags to `false`. -3. **Updated `SmartButton`**: Added a check. If `step === 'declare_attackers'` AND `attackersDeclared` is true, display "Pass (to Blockers)" with `PASS_PRIORITY` action instead of "Skip Combat" / `DECLARE_ATTACKERS`. - -## Outcome -When a user clicks "Skip Combat" (declares 0 attackers), the server updates the state flag. The UI then updates to show a "Pass" button, allowing the user to proceed to the next step. diff --git a/docs/development/devlog/2024-12-18-193000_strict_blocking_ui.md b/docs/development/devlog/2024-12-18-193000_strict_blocking_ui.md deleted file mode 100644 index fbed200..0000000 --- a/docs/development/devlog/2024-12-18-193000_strict_blocking_ui.md +++ /dev/null @@ -1,37 +0,0 @@ -# Strict Rules & Blocking UI (Part 3) - -## Status: Completed - -## Objectives -- Integrate Strict Actions (`PLAY_LAND`, `CAST_SPELL`) with precise positioning. -- Implement Blocking UI including visual feedback (Attacking/Blocking badges, Rings). -- Implement Drag-and-Drop Targeting Logic (Spell -> Target, Blocker -> Attacker). -- Implement Visual "Targeting Tether" overlay. - -## Implementation Details - -### Backend (Rules Engine) -- **Positioning**: Updated `playLand` and `castSpell` to accept `{x, y}` coordinates. -- **Stack Resolution**: Updated `resolveTopStack` to respect the stored resolution position when moving cards to the battlefield. -- **Action Handling**: Updated `GameManager` to pass `position` payload to the engine. - -### Frontend (GameView) -- **Drop Logic**: - - `handleZoneDrop`: Detects drop on "Battlefield". Differentiates Land (Play) vs Spell (Cast). Calculates relative % coordinates. - - `handleCardDrop`: Detects drop on a Card. - - If `declare_blockers` step: Assigns blocker (drag My Creature -> Opponent Creature). - - Else: Casts Spell with Target. - - `handlePlayerDrop`: Detects drop on Opponent Avatar -> Cast Spell with Target Player. -- **Blocking Visualization**: - - **Opponent Cards**: Show "ATTACKING" badge (Red Ring + Shadow) if `attacking === property`. - - **My Cards**: Show "Blocking" badge (Blue Ring) if in local `proposedBlockers` map. -- **Targeting Tether**: - - Implemented `tether` state (`startX`, `currentX`, etc.). - - Added `onDrag` handler to `CardComponent` to track HTML5 DnD movement. - - Rendered Full-screen SVG overlay with Bezier curve (`Q` command) and arrow marker. - - Dynamic styling: Cyan (Spells) vs Blue (Blocking). - -## Next Steps -- **Layer System**: Implement 7-layer P/T calculation for accurate power/toughness display. -- **Mulligan System**: Implement Strict Mulligan rules. -- **Token Creation**: Support creating tokens. diff --git a/docs/development/devlog/2024-12-18-193500_force_combat_skip.md b/docs/development/devlog/2024-12-18-193500_force_combat_skip.md deleted file mode 100644 index f72ceb9..0000000 --- a/docs/development/devlog/2024-12-18-193500_force_combat_skip.md +++ /dev/null @@ -1,15 +0,0 @@ -# 2024-12-18 - Fix Empty Combat Step Skipping - -## Problem -When a player declares 0 attackers (Skip Combat), the game correctly advances from `declare_attackers` but then proceeds to `declare_blockers` instead of skipping to the end of combat. This forces the (non-existent) defending player to declare blockers against nothing, or the active player to wait through irrelevant priority passes. - -## Root Cause -The `RulesEngine.advanceStep()` method strictly followed the standard phase/step structure defined in `server/game/RulesEngine.ts`. It lacked the logic to implement Rule 508.8, which states that if no attackers are declared, the Declare Blockers and Combat Damage steps are skipped. - -## Solution -Modified `RulesEngine.advanceStep()` to check for attackers before transitioning steps. -If the current phase is `combat` and the next projected step is `declare_blockers`, it checks if any cards have the `attacking` property. -If `attackers.length === 0`, it overrides `nextStep` to `end_combat`, effectively skipping the interactive combat steps. - -## Outcome -Declaring 0 attackers (or passing with no attacks) now correctly transitions the game immediately to the "End of Combat" step (and then likely Main Phase 2), smoothing out the gameplay flow. diff --git a/docs/development/devlog/2024-12-18-200000_engine_enhancements.md b/docs/development/devlog/2024-12-18-200000_engine_enhancements.md deleted file mode 100644 index b272914..0000000 --- a/docs/development/devlog/2024-12-18-200000_engine_enhancements.md +++ /dev/null @@ -1,45 +0,0 @@ -# Strict Engine Enhancements: Layers, Tokens, Mulligan - -## Status: Completed - -## Objectives -- Implement Basic Layer System for continuous effects (P/T modifications). -- Implement Token Creation mechanism. -- Implement Mulligan System (London Rule). -- Update Game Lifecycle to include Setup/Mulligan phase. - -## Logic Overview - -### Layer System (`RulesEngine.recalculateLayers`) -- Implements Layer 7 (Power/Toughness) basics: - - **Layer 7b**: Set P/T (`set_pt`). - - **Layer 7c**: Modify P/T (`pt_boost`). - - **Layer 7d**: Counters (`+1/+1`, `-1/-1`). -- `recalculateLayers` is called automatically whenever priority resets or actions occur. -- Modifiers with `untilEndOfTurn: true` are automatically cleared in the `cleanup` step. - -### Token Creation -- New action `CREATE_TOKEN` added. -- `createToken` method constructs a CardObject on the battlefield with defined stats. -- Triggers layer recalculation immediately. - -### Mulligan System -- **New Phase**: `setup`, **New Step**: `mulligan`. -- Game starts in `setup/mulligan`. -- **Logic**: - - If a player has 0 cards and hasn't kept, they draw 7 automatically. - - Action `MULLIGAN_DECISION`: - - `keep: false` -> Shuffles hand into library, draws 7, increments `mulliganCount`. - - `keep: true` -> Validates `cardsToBottom` count matches `mulliganCount`. Moves excess cards to library. Sets `handKept = true`. -- When all players keep, the engine automatically advances to `beginning/untap`. -- Supports London Mulligan rule (Draw 7, put X on bottom). - -## Technical Changes -- Updated `StrictGameState` and `PlayerState` types. -- Updated `GameManager` initialization and action switching. -- Updated `RulesEngine` transition logic. - -## Remaining/Next -- Frontend UI for Mulligan (Needs a Modal to Keep/Mull). -- Frontend UI for "Cards to Bottom" selection if X > 0. -- Frontend UI to visualize Tokens. diff --git a/docs/development/devlog/2024-12-18-220000_ux_and_engine_completion.md b/docs/development/devlog/2024-12-18-220000_ux_and_engine_completion.md deleted file mode 100644 index 4c18ee0..0000000 --- a/docs/development/devlog/2024-12-18-220000_ux_and_engine_completion.md +++ /dev/null @@ -1,26 +0,0 @@ -# 2024-12-18 - High Velocity UX & Strict Engine Completion - -## Status: Completed - -We have successfully implemented the core strict rules engine features and the high-velocity UX components. - -### 1. Rules Engine Refinement -- **State-Based Actions (SBAs)**: Implemented robust SBA loop in `RulesEngine.ts`, utilizing `processStateBasedActions()` to cyclically check conditions (Lethal Damage, Legend Rule, Aura Validity) and recalculate layers until stability. -- **Layer System**: Implemented Layer 7 (Power/Toughness) calculations, handling Base P/T, Setting Effects, Boosts, and Counters. -- **Mana Engine**: Backend support for manual mana pool management (emptying at end of steps). -- **Code Cleanup**: Resolved critical linting errors and structural issues in `RulesEngine.ts` (duplicate methods, undefined checks). - -### 2. High-Velocity Frontend UX -- **Inspector Overlay**: Created `InspectorOverlay.tsx` to visualize detailed card state (P/T modifications, counters, oracle text) with a modern, glassmorphism UI. -- **Smart Button Advanced**: Implemented "Yield" toggle on the Smart Button. Users can long-press (simulated via pointer down) to yield priority until end of turn (or cancel). -- **Radial Menu**: Created a generic `RadialMenu.tsx` component. Integrated it into the `GameView` via the Context Menu ("Add Mana...") to allow quick manual mana color selection for dual/utility lands. -- **Context Menu Integration**: Added "Inspect Details" and "Add Mana..." options to the card context menu. - -### 3. Verification -- **GameView Integration**: All new components (`InspectorOverlay`, `SmartButton`, `RadialMenu`) are fully integrated into `GameView.ts`. -- **Type Safety**: Updated `types/game.ts` to ensure consistency between client and server (e.g., `attachedTo`, `ptModification` properties). - -## Next Steps -- **Playtesting**: Validate the interaction between strict rules (timing, priority) and the new UX in a live multiplayer environment. -- **Visual Polish**: Refine animations for Inspector and Radial Menu opening. -- **Complex Card Logic**: Expand the engine to support more complex replacement effects and specific card scripts. diff --git a/docs/development/devlog/2025-12-14-190500_initial_project_setup.md b/docs/development/devlog/2025-12-14-190500_initial_project_setup.md deleted file mode 100644 index 656514a..0000000 --- a/docs/development/devlog/2025-12-14-190500_initial_project_setup.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-14-193500_migration_to_nodejs.md b/docs/development/devlog/2025-12-14-193500_migration_to_nodejs.md deleted file mode 100644 index 708b717..0000000 --- a/docs/development/devlog/2025-12-14-193500_migration_to_nodejs.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-14-194558_core_implementation.md b/docs/development/devlog/2025-12-14-194558_core_implementation.md deleted file mode 100644 index 29b0b73..0000000 --- a/docs/development/devlog/2025-12-14-194558_core_implementation.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-14-203000_fix_root_render_generation.md b/docs/development/devlog/2025-12-14-203000_fix_root_render_generation.md deleted file mode 100644 index bf7b5a5..0000000 --- a/docs/development/devlog/2025-12-14-203000_fix_root_render_generation.md +++ /dev/null @@ -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( 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. diff --git a/docs/development/devlog/2025-12-14-210000_fix_parser_robustness.md b/docs/development/devlog/2025-12-14-210000_fix_parser_robustness.md deleted file mode 100644 index e3caf48..0000000 --- a/docs/development/devlog/2025-12-14-210000_fix_parser_robustness.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-14-211000_set_based_generation.md b/docs/development/devlog/2025-12-14-211000_set_based_generation.md deleted file mode 100644 index aabed6d..0000000 --- a/docs/development/devlog/2025-12-14-211000_set_based_generation.md +++ /dev/null @@ -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". diff --git a/docs/development/devlog/2025-12-14-211500_remove_tournament_mode.md b/docs/development/devlog/2025-12-14-211500_remove_tournament_mode.md deleted file mode 100644 index 3c14f32..0000000 --- a/docs/development/devlog/2025-12-14-211500_remove_tournament_mode.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-14-212000_ui_simplification.md b/docs/development/devlog/2025-12-14-212000_ui_simplification.md deleted file mode 100644 index c79dd54..0000000 --- a/docs/development/devlog/2025-12-14-212000_ui_simplification.md +++ /dev/null @@ -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"). diff --git a/docs/development/devlog/2025-12-14-212500_multiplayer_game_plan.md b/docs/development/devlog/2025-12-14-212500_multiplayer_game_plan.md deleted file mode 100644 index 7946aad..0000000 --- a/docs/development/devlog/2025-12-14-212500_multiplayer_game_plan.md +++ /dev/null @@ -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). diff --git a/docs/development/devlog/2025-12-14-214400_fix_uuid_error.md b/docs/development/devlog/2025-12-14-214400_fix_uuid_error.md deleted file mode 100644 index 4e817dc..0000000 --- a/docs/development/devlog/2025-12-14-214400_fix_uuid_error.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-14-220000_game_interactions.md b/docs/development/devlog/2025-12-14-220000_game_interactions.md deleted file mode 100644 index bcfcbee..0000000 --- a/docs/development/devlog/2025-12-14-220000_game_interactions.md +++ /dev/null @@ -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). diff --git a/docs/development/devlog/2025-12-14-223000_draft_and_deckbuilder.md b/docs/development/devlog/2025-12-14-223000_draft_and_deckbuilder.md deleted file mode 100644 index f8e78e6..0000000 --- a/docs/development/devlog/2025-12-14-223000_draft_and_deckbuilder.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-14-224500_image_caching.md b/docs/development/devlog/2025-12-14-224500_image_caching.md deleted file mode 100644 index 6aa27b2..0000000 --- a/docs/development/devlog/2025-12-14-224500_image_caching.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-14-230000_fix_draft_images.md b/docs/development/devlog/2025-12-14-230000_fix_draft_images.md deleted file mode 100644 index 12b4911..0000000 --- a/docs/development/devlog/2025-12-14-230000_fix_draft_images.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-14-233000_fix_submit_deck.md b/docs/development/devlog/2025-12-14-233000_fix_submit_deck.md deleted file mode 100644 index 88701c4..0000000 --- a/docs/development/devlog/2025-12-14-233000_fix_submit_deck.md +++ /dev/null @@ -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). diff --git a/docs/development/devlog/2025-12-14-234500_fix_hooks_and_waiting_state.md b/docs/development/devlog/2025-12-14-234500_fix_hooks_and_waiting_state.md deleted file mode 100644 index ee10070..0000000 --- a/docs/development/devlog/2025-12-14-234500_fix_hooks_and_waiting_state.md +++ /dev/null @@ -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). diff --git a/docs/development/devlog/2025-12-14-234500_game_battlefield_plan.md b/docs/development/devlog/2025-12-14-234500_game_battlefield_plan.md deleted file mode 100644 index 5d6ac18..0000000 --- a/docs/development/devlog/2025-12-14-234500_game_battlefield_plan.md +++ /dev/null @@ -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). diff --git a/docs/development/devlog/2025-12-14-235000_game_context_menu.md b/docs/development/devlog/2025-12-14-235000_game_context_menu.md deleted file mode 100644 index 6786e6e..0000000 --- a/docs/development/devlog/2025-12-14-235000_game_context_menu.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-14-235500_enhance_3d_game_view.md b/docs/development/devlog/2025-12-14-235500_enhance_3d_game_view.md deleted file mode 100644 index 0ad08de..0000000 --- a/docs/development/devlog/2025-12-14-235500_enhance_3d_game_view.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-14-235700_docker_containerization.md b/docs/development/devlog/2025-12-14-235700_docker_containerization.md deleted file mode 100644 index 2f6afbb..0000000 --- a/docs/development/devlog/2025-12-14-235700_docker_containerization.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-15-002500_deck_tester_feature.md b/docs/development/devlog/2025-12-15-002500_deck_tester_feature.md deleted file mode 100644 index b2c7add..0000000 --- a/docs/development/devlog/2025-12-15-002500_deck_tester_feature.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-16-131921_export_generated_packs_csv b/docs/development/devlog/2025-12-16-131921_export_generated_packs_csv deleted file mode 100644 index 27ba954..0000000 --- a/docs/development/devlog/2025-12-16-131921_export_generated_packs_csv +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-16-152253_csv_import_robustness.md b/docs/development/devlog/2025-12-16-152253_csv_import_robustness.md deleted file mode 100644 index 6e4e93d..0000000 --- a/docs/development/devlog/2025-12-16-152253_csv_import_robustness.md +++ /dev/null @@ -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). diff --git a/docs/development/devlog/2025-12-16-180000_draft_rules_implementation.md b/docs/development/devlog/2025-12-16-180000_draft_rules_implementation.md deleted file mode 100644 index 981f562..0000000 --- a/docs/development/devlog/2025-12-16-180000_draft_rules_implementation.md +++ /dev/null @@ -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). diff --git a/docs/development/devlog/2025-12-16-183000_fix_socket_mixed_content.md b/docs/development/devlog/2025-12-16-183000_fix_socket_mixed_content.md deleted file mode 100644 index 7a769eb..0000000 --- a/docs/development/devlog/2025-12-16-183000_fix_socket_mixed_content.md +++ /dev/null @@ -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 `/// ` 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. diff --git a/docs/development/devlog/2025-12-16-184500_fix_pack_duplication.md b/docs/development/devlog/2025-12-16-184500_fix_pack_duplication.md deleted file mode 100644 index e098ea8..0000000 --- a/docs/development/devlog/2025-12-16-184500_fix_pack_duplication.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-16-191500_reconnection_and_autopick.md b/docs/development/devlog/2025-12-16-191500_reconnection_and_autopick.md deleted file mode 100644 index 0815327..0000000 --- a/docs/development/devlog/2025-12-16-191500_reconnection_and_autopick.md +++ /dev/null @@ -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.). diff --git a/docs/development/devlog/2025-12-16-195000_draft_ui_polish.md b/docs/development/devlog/2025-12-16-195000_draft_ui_polish.md deleted file mode 100644 index 2749ec7..0000000 --- a/docs/development/devlog/2025-12-16-195000_draft_ui_polish.md +++ /dev/null @@ -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`). diff --git a/docs/development/devlog/2025-12-16-200500_resizable_draft_ui.md b/docs/development/devlog/2025-12-16-200500_resizable_draft_ui.md deleted file mode 100644 index 40efe19..0000000 --- a/docs/development/devlog/2025-12-16-200500_resizable_draft_ui.md +++ /dev/null @@ -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 (``) 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). diff --git a/docs/development/devlog/2025-12-16-201500_card_zoom.md b/docs/development/devlog/2025-12-16-201500_card_zoom.md deleted file mode 100644 index 087aeaf..0000000 --- a/docs/development/devlog/2025-12-16-201500_card_zoom.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-16-203000_zoom_zone.md b/docs/development/devlog/2025-12-16-203000_zoom_zone.md deleted file mode 100644 index 424e34c..0000000 --- a/docs/development/devlog/2025-12-16-203000_zoom_zone.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-16-213500_host_disconnect_pause.md b/docs/development/devlog/2025-12-16-213500_host_disconnect_pause.md deleted file mode 100644 index e02a0ed..0000000 --- a/docs/development/devlog/2025-12-16-213500_host_disconnect_pause.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-16-215000_anti_tampering.md b/docs/development/devlog/2025-12-16-215000_anti_tampering.md deleted file mode 100644 index 5b2b14d..0000000 --- a/docs/development/devlog/2025-12-16-215000_anti_tampering.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-16-215500_fix_draft_ui_layout.md b/docs/development/devlog/2025-12-16-215500_fix_draft_ui_layout.md deleted file mode 100644 index e3a216d..0000000 --- a/docs/development/devlog/2025-12-16-215500_fix_draft_ui_layout.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-16-220000_session_persistence.md b/docs/development/devlog/2025-12-16-220000_session_persistence.md deleted file mode 100644 index c383674..0000000 --- a/docs/development/devlog/2025-12-16-220000_session_persistence.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-16-221000_lobby_improvements.md b/docs/development/devlog/2025-12-16-221000_lobby_improvements.md deleted file mode 100644 index 6d64b02..0000000 --- a/docs/development/devlog/2025-12-16-221000_lobby_improvements.md +++ /dev/null @@ -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). diff --git a/docs/development/devlog/2025-12-16-222500_draft_timer.md b/docs/development/devlog/2025-12-16-222500_draft_timer.md deleted file mode 100644 index 345fac1..0000000 --- a/docs/development/devlog/2025-12-16-222500_draft_timer.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-16-223000_enhance_metadata.md b/docs/development/devlog/2025-12-16-223000_enhance_metadata.md deleted file mode 100644 index 01e1345..0000000 --- a/docs/development/devlog/2025-12-16-223000_enhance_metadata.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-16-224000_pack_generation_update.md b/docs/development/devlog/2025-12-16-224000_pack_generation_update.md deleted file mode 100644 index a6bb7e2..0000000 --- a/docs/development/devlog/2025-12-16-224000_pack_generation_update.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-16-224500_card_metadata_enhancement.md b/docs/development/devlog/2025-12-16-224500_card_metadata_enhancement.md deleted file mode 100644 index dbe0e45..0000000 --- a/docs/development/devlog/2025-12-16-224500_card_metadata_enhancement.md +++ /dev/null @@ -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). diff --git a/docs/development/devlog/2025-12-16-225700_peasant_algorithm.md b/docs/development/devlog/2025-12-16-225700_peasant_algorithm.md deleted file mode 100644 index ffdc579..0000000 --- a/docs/development/devlog/2025-12-16-225700_peasant_algorithm.md +++ /dev/null @@ -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). diff --git a/docs/development/devlog/2025-12-16-230000_persist_metadata.md b/docs/development/devlog/2025-12-16-230000_persist_metadata.md deleted file mode 100644 index 805883c..0000000 --- a/docs/development/devlog/2025-12-16-230000_persist_metadata.md +++ /dev/null @@ -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). diff --git a/docs/development/devlog/2025-12-16-230500_multi_expansion_selection.md b/docs/development/devlog/2025-12-16-230500_multi_expansion_selection.md deleted file mode 100644 index 4502e35..0000000 --- a/docs/development/devlog/2025-12-16-230500_multi_expansion_selection.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-16-231000_game_type_filter.md b/docs/development/devlog/2025-12-16-231000_game_type_filter.md deleted file mode 100644 index f45a9d3..0000000 --- a/docs/development/devlog/2025-12-16-231000_game_type_filter.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-16-231500_bulk_parse_feedback.md b/docs/development/devlog/2025-12-16-231500_bulk_parse_feedback.md deleted file mode 100644 index a95fed8..0000000 --- a/docs/development/devlog/2025-12-16-231500_bulk_parse_feedback.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-16-233000_incremental_caching.md b/docs/development/devlog/2025-12-16-233000_incremental_caching.md deleted file mode 100644 index 48fb58e..0000000 --- a/docs/development/devlog/2025-12-16-233000_incremental_caching.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-16-234500_full_metadata_passthrough.md b/docs/development/devlog/2025-12-16-234500_full_metadata_passthrough.md deleted file mode 100644 index 42000bf..0000000 --- a/docs/development/devlog/2025-12-16-234500_full_metadata_passthrough.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-16-235900_server_side_caching.md b/docs/development/devlog/2025-12-16-235900_server_side_caching.md deleted file mode 100644 index e5cf0e3..0000000 --- a/docs/development/devlog/2025-12-16-235900_server_side_caching.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-002000_server_shutdown_fix.md b/docs/development/devlog/2025-12-17-002000_server_shutdown_fix.md deleted file mode 100644 index 7882a43..0000000 --- a/docs/development/devlog/2025-12-17-002000_server_shutdown_fix.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-003000_cube_sticky_sidebar.md b/docs/development/devlog/2025-12-17-003000_cube_sticky_sidebar.md deleted file mode 100644 index 3a78d26..0000000 --- a/docs/development/devlog/2025-12-17-003000_cube_sticky_sidebar.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-003500_cube_full_width.md b/docs/development/devlog/2025-12-17-003500_cube_full_width.md deleted file mode 100644 index 1f38d85..0000000 --- a/docs/development/devlog/2025-12-17-003500_cube_full_width.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-004500_archidekt_view.md b/docs/development/devlog/2025-12-17-004500_archidekt_view.md deleted file mode 100644 index 8cf29e2..0000000 --- a/docs/development/devlog/2025-12-17-004500_archidekt_view.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-005000_mobile_ui_fixes.md b/docs/development/devlog/2025-12-17-005000_mobile_ui_fixes.md deleted file mode 100644 index 0669523..0000000 --- a/docs/development/devlog/2025-12-17-005000_mobile_ui_fixes.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-005500_mobile_long_press.md b/docs/development/devlog/2025-12-17-005500_mobile_long_press.md deleted file mode 100644 index b7c343d..0000000 --- a/docs/development/devlog/2025-12-17-005500_mobile_long_press.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-010000_mobile_fullscreen_preview.md b/docs/development/devlog/2025-12-17-010000_mobile_fullscreen_preview.md deleted file mode 100644 index 9acae7c..0000000 --- a/docs/development/devlog/2025-12-17-010000_mobile_fullscreen_preview.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-010500_mobile_preview_animations.md b/docs/development/devlog/2025-12-17-010500_mobile_preview_animations.md deleted file mode 100644 index 0817309..0000000 --- a/docs/development/devlog/2025-12-17-010500_mobile_preview_animations.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-011000_mobile_preview_polish.md b/docs/development/devlog/2025-12-17-011000_mobile_preview_polish.md deleted file mode 100644 index 2a793ea..0000000 --- a/docs/development/devlog/2025-12-17-011000_mobile_preview_polish.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-011500_enhanced_foils.md b/docs/development/devlog/2025-12-17-011500_enhanced_foils.md deleted file mode 100644 index b7988ac..0000000 --- a/docs/development/devlog/2025-12-17-011500_enhanced_foils.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-012000_rolling_rainbow_foil.md b/docs/development/devlog/2025-12-17-012000_rolling_rainbow_foil.md deleted file mode 100644 index f1791d5..0000000 --- a/docs/development/devlog/2025-12-17-012000_rolling_rainbow_foil.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-013000_card_visibility_boost.md b/docs/development/devlog/2025-12-17-013000_card_visibility_boost.md deleted file mode 100644 index 458415a..0000000 --- a/docs/development/devlog/2025-12-17-013000_card_visibility_boost.md +++ /dev/null @@ -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 `
` 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. diff --git a/docs/development/devlog/2025-12-17-013500_optimized_rolling_foil.md b/docs/development/devlog/2025-12-17-013500_optimized_rolling_foil.md deleted file mode 100644 index e539eb2..0000000 --- a/docs/development/devlog/2025-12-17-013500_optimized_rolling_foil.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-014000_metallic_foil_refinement.md b/docs/development/devlog/2025-12-17-014000_metallic_foil_refinement.md deleted file mode 100644 index c973232..0000000 --- a/docs/development/devlog/2025-12-17-014000_metallic_foil_refinement.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-014500_circular_foil_animation.md b/docs/development/devlog/2025-12-17-014500_circular_foil_animation.md deleted file mode 100644 index 2f729c2..0000000 --- a/docs/development/devlog/2025-12-17-014500_circular_foil_animation.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-015000_mild_foil_animation.md b/docs/development/devlog/2025-12-17-015000_mild_foil_animation.md deleted file mode 100644 index 42e3e5e..0000000 --- a/docs/development/devlog/2025-12-17-015000_mild_foil_animation.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-020000_pro_foil_implementation.md b/docs/development/devlog/2025-12-17-020000_pro_foil_implementation.md deleted file mode 100644 index 7bb42cd..0000000 --- a/docs/development/devlog/2025-12-17-020000_pro_foil_implementation.md +++ /dev/null @@ -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"). diff --git a/docs/development/devlog/2025-12-17-020500_universal_preview_animations.md b/docs/development/devlog/2025-12-17-020500_universal_preview_animations.md deleted file mode 100644 index e363167..0000000 --- a/docs/development/devlog/2025-12-17-020500_universal_preview_animations.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-021000_mobile_touch_fix.md b/docs/development/devlog/2025-12-17-021000_mobile_touch_fix.md deleted file mode 100644 index 6323998..0000000 --- a/docs/development/devlog/2025-12-17-021000_mobile_touch_fix.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-021500_entrance_animation_fix.md b/docs/development/devlog/2025-12-17-021500_entrance_animation_fix.md deleted file mode 100644 index 3469d0e..0000000 --- a/docs/development/devlog/2025-12-17-021500_entrance_animation_fix.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-022000_foil_bug_fix.md b/docs/development/devlog/2025-12-17-022000_foil_bug_fix.md deleted file mode 100644 index 9659dc9..0000000 --- a/docs/development/devlog/2025-12-17-022000_foil_bug_fix.md +++ /dev/null @@ -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 `` component, which encapsulates the foil logic correctly. - - Wrapped this component call in the `{isFoil && }` 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. diff --git a/docs/development/devlog/2025-12-17-022000_replace_alert_with_toast.md b/docs/development/devlog/2025-12-17-022000_replace_alert_with_toast.md deleted file mode 100644 index aa3b88d..0000000 --- a/docs/development/devlog/2025-12-17-022000_replace_alert_with_toast.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-022500_universal_foil_application.md b/docs/development/devlog/2025-12-17-022500_universal_foil_application.md deleted file mode 100644 index 89bfbc9..0000000 --- a/docs/development/devlog/2025-12-17-022500_universal_foil_application.md +++ /dev/null @@ -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 `` component. -- **StackView.tsx**: - - Imported `FoilOverlay`. - - Replaced the simple opacity layer for foil cards with the `` 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. diff --git a/docs/development/devlog/2025-12-17-023000_enhanced_toast_visibility.md b/docs/development/devlog/2025-12-17-023000_enhanced_toast_visibility.md deleted file mode 100644 index 047c16e..0000000 --- a/docs/development/devlog/2025-12-17-023000_enhanced_toast_visibility.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-023000_smart_preview_suppression.md b/docs/development/devlog/2025-12-17-023000_smart_preview_suppression.md deleted file mode 100644 index 98be908..0000000 --- a/docs/development/devlog/2025-12-17-023000_smart_preview_suppression.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-023500_compact_card_layout.md b/docs/development/devlog/2025-12-17-023500_compact_card_layout.md deleted file mode 100644 index fdb9004..0000000 --- a/docs/development/devlog/2025-12-17-023500_compact_card_layout.md +++ /dev/null @@ -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). diff --git a/docs/development/devlog/2025-12-17-023500_unified_toast_design.md b/docs/development/devlog/2025-12-17-023500_unified_toast_design.md deleted file mode 100644 index e810a21..0000000 --- a/docs/development/devlog/2025-12-17-023500_unified_toast_design.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-024000_animated_copy_button.md b/docs/development/devlog/2025-12-17-024000_animated_copy_button.md deleted file mode 100644 index 55f2e95..0000000 --- a/docs/development/devlog/2025-12-17-024000_animated_copy_button.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-024000_view_scale_slider.md b/docs/development/devlog/2025-12-17-024000_view_scale_slider.md deleted file mode 100644 index 14df8fa..0000000 --- a/docs/development/devlog/2025-12-17-024000_view_scale_slider.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-024500_dynamic_art_cropping.md b/docs/development/devlog/2025-12-17-024500_dynamic_art_cropping.md deleted file mode 100644 index eab0a3a..0000000 --- a/docs/development/devlog/2025-12-17-024500_dynamic_art_cropping.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-024500_fix_expansion_generation_limit.md b/docs/development/devlog/2025-12-17-024500_fix_expansion_generation_limit.md deleted file mode 100644 index 8c03c72..0000000 --- a/docs/development/devlog/2025-12-17-024500_fix_expansion_generation_limit.md +++ /dev/null @@ -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 diff --git a/docs/development/devlog/2025-12-17-024600_mobile_long_press_preview.md b/docs/development/devlog/2025-12-17-024600_mobile_long_press_preview.md deleted file mode 100644 index c7b9cf1..0000000 --- a/docs/development/devlog/2025-12-17-024600_mobile_long_press_preview.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-024800_mobile_card_slider.md b/docs/development/devlog/2025-12-17-024800_mobile_card_slider.md deleted file mode 100644 index c563a4d..0000000 --- a/docs/development/devlog/2025-12-17-024800_mobile_card_slider.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-025000_refined_preview_suppression.md b/docs/development/devlog/2025-12-17-025000_refined_preview_suppression.md deleted file mode 100644 index 4a05119..0000000 --- a/docs/development/devlog/2025-12-17-025000_refined_preview_suppression.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-025500_change_default_flags.md b/docs/development/devlog/2025-12-17-025500_change_default_flags.md deleted file mode 100644 index ddf953e..0000000 --- a/docs/development/devlog/2025-12-17-025500_change_default_flags.md +++ /dev/null @@ -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`. diff --git a/docs/development/devlog/2025-12-17-025500_explicit_preview_suppression.md b/docs/development/devlog/2025-12-17-025500_explicit_preview_suppression.md deleted file mode 100644 index 4710b50..0000000 --- a/docs/development/devlog/2025-12-17-025500_explicit_preview_suppression.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-030000_synchronized_boundaries.md b/docs/development/devlog/2025-12-17-030000_synchronized_boundaries.md deleted file mode 100644 index 5c9e7af..0000000 --- a/docs/development/devlog/2025-12-17-030000_synchronized_boundaries.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-030500_squared_art_crops.md b/docs/development/devlog/2025-12-17-030500_squared_art_crops.md deleted file mode 100644 index 1123984..0000000 --- a/docs/development/devlog/2025-12-17-030500_squared_art_crops.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-030600_fix_strict_pack_generation.md b/docs/development/devlog/2025-12-17-030600_fix_strict_pack_generation.md deleted file mode 100644 index 225ae30..0000000 --- a/docs/development/devlog/2025-12-17-030600_fix_strict_pack_generation.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-031000_sidebar_max_width.md b/docs/development/devlog/2025-12-17-031000_sidebar_max_width.md deleted file mode 100644 index d76e5cc..0000000 --- a/docs/development/devlog/2025-12-17-031000_sidebar_max_width.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-031500_play_online_logic.md b/docs/development/devlog/2025-12-17-031500_play_online_logic.md deleted file mode 100644 index c333a32..0000000 --- a/docs/development/devlog/2025-12-17-031500_play_online_logic.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-032000_lobby_rules_tooltip.md b/docs/development/devlog/2025-12-17-032000_lobby_rules_tooltip.md deleted file mode 100644 index 1f855ea..0000000 --- a/docs/development/devlog/2025-12-17-032000_lobby_rules_tooltip.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-140000_fix_expansion_generation.md b/docs/development/devlog/2025-12-17-140000_fix_expansion_generation.md deleted file mode 100644 index 650473d..0000000 --- a/docs/development/devlog/2025-12-17-140000_fix_expansion_generation.md +++ /dev/null @@ -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'`. diff --git a/docs/development/devlog/2025-12-17-142500_responsive_pack_grid.md b/docs/development/devlog/2025-12-17-142500_responsive_pack_grid.md deleted file mode 100644 index 2da151f..0000000 --- a/docs/development/devlog/2025-12-17-142500_responsive_pack_grid.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-143000_stack_view_consistency.md b/docs/development/devlog/2025-12-17-143000_stack_view_consistency.md deleted file mode 100644 index 4bc829d..0000000 --- a/docs/development/devlog/2025-12-17-143000_stack_view_consistency.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-144000_dynamic_pack_grid.md b/docs/development/devlog/2025-12-17-144000_dynamic_pack_grid.md deleted file mode 100644 index 9c154ab..0000000 --- a/docs/development/devlog/2025-12-17-144000_dynamic_pack_grid.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-152700_fix_socket_payload_limit.md b/docs/development/devlog/2025-12-17-152700_fix_socket_payload_limit.md deleted file mode 100644 index 372c510..0000000 --- a/docs/development/devlog/2025-12-17-152700_fix_socket_payload_limit.md +++ /dev/null @@ -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). diff --git a/docs/development/devlog/2025-12-17-153300_basic_lands_handling.md b/docs/development/devlog/2025-12-17-153300_basic_lands_handling.md deleted file mode 100644 index 94d3475..0000000 --- a/docs/development/devlog/2025-12-17-153300_basic_lands_handling.md +++ /dev/null @@ -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. diff --git a/docs/development/devlog/2025-12-17-155500_land_advice_and_unlimited_time.md b/docs/development/devlog/2025-12-17-155500_land_advice_and_unlimited_time.md deleted file mode 100644 index 5f5f292..0000000 --- a/docs/development/devlog/2025-12-17-155500_land_advice_and_unlimited_time.md +++ /dev/null @@ -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("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. diff --git a/docs/development/devlog/2025-12-17-160500_deck_builder_magnified_view.md b/docs/development/devlog/2025-12-17-160500_deck_builder_magnified_view.md deleted file mode 100644 index f8da087..0000000 --- a/docs/development/devlog/2025-12-17-160500_deck_builder_magnified_view.md +++ /dev/null @@ -1,27 +0,0 @@ -# Deck Builder Magnified View - -## Requirements -- Add a magnified card view to the `DeckBuilderView`, similar to the one in `DraftView`. -- Show card details (name, type, oracle text) when hovering over any card in the pool, deck, or land station. -- Use a persistent sidebar layout for the magnified view. - -## Implementation Details - -### `DeckBuilderView.tsx` - -- **State**: Added `hoveredCard` state to track the card being inspected. -- **Layout**: - - Changed the layout to a 3-column flex design: - 1. **Zoom Sidebar** (`hidden xl:flex w-80`): Shows the magnified card image and text details. Defaults to a "Hover Card" placeholder. - 2. **Card Pool** (`flex-1`): Displays available cards. - 3. **Deck & Lands** (`flex-1`): Displays the current deck and land controls. -- **Interactions**: - - Added `onMouseEnter={() => setHoveredCard(card)}` and `onMouseLeave={() => setHoveredCard(null)}` handlers to: - - Cards in the Pool. - - Cards in the current Deck. - - Basic Lands in the Land Station. - -## Verification -- Verified that hovering over cards updates the sidebar image and text. -- Verified that moving mouse away clears the preview (consistent with Draft View). -- Layout adjusts responsively (sidebar hidden on smaller screens). diff --git a/docs/development/devlog/2025-12-17-161500_gameplay_magnified_view_and_timeout.md b/docs/development/devlog/2025-12-17-161500_gameplay_magnified_view_and_timeout.md deleted file mode 100644 index 7e007d6..0000000 --- a/docs/development/devlog/2025-12-17-161500_gameplay_magnified_view_and_timeout.md +++ /dev/null @@ -1,24 +0,0 @@ -# Gameplay Magnified View Details Update - -## Requirements -- Display detailed card information (Oracle Text, Type Line, Mana Cost) in the magnified view on the battlefield. - -## Implementation Details - -### Data Model Updates -- **`CardInstance` Interface**: Added optional fields `typeLine`, `oracleText`, and `manaCost` to both client (`src/client/src/types/game.ts`) and server (`src/server/managers/GameManager.ts`) definitions. -- **`DraftCard` Interface**: Added `oracleText` and `manaCost` to the server-side interface (`PackGeneratorService.ts`). - -### Logic Updates -- **`PackGeneratorService.ts`**: Updated `processCards` to map `oracle_text` and `mana_cost` from Scryfall data to `DraftCard`. -- **`src/server/index.ts`**: Updated all `addCardToGame` calls (timeout handling, player ready, solo test, start game) to pass the new fields from the draft card/deck source to the `CardInstance`. - -### UI Updates (`GameView.tsx`) -- Updated the **Zoom Sidebar** to conditionally render: - - **Mana Cost**: Displayed in a monospace font. - - **Type Line**: Displayed in emerald color with uppercase styling. - - **Oracle Text**: Displayed in a formatted block with proper whitespace handling. -- Replaced undefined `cardIsCreature` helper with an inline check. - -## Verification -- Hovering over a card in the game view now shows not just the image but also the text details, which is crucial for readability of complex cards. diff --git a/docs/development/devlog/2025-12-17-162500_test_deck_feature.md b/docs/development/devlog/2025-12-17-162500_test_deck_feature.md deleted file mode 100644 index b34e2a9..0000000 --- a/docs/development/devlog/2025-12-17-162500_test_deck_feature.md +++ /dev/null @@ -1,32 +0,0 @@ -# Test Deck Feature Implementation - -## Requirements -- Allow users to "Test Deck" directly from the Cube Manager (Pack Generator). -- Create a randomized deck from the generated pool (approx. 23 spells + 17 lands). -- Start a solo game immediately. -- Enable return to lobby. - -## Implementation Details - -### Client-Side Updates -- **`App.tsx`**: Passed `availableLands` to `CubeManager` to allow for proper basic land inclusion in randomized decks. -- **`CubeManager.tsx`**: - - Added `handleStartSoloTest` function. - - Logic: Flattens generated packs, separates lands/spells, shuffles and picks 23 spells, adds 17 basic lands (using `availableLands` if available). - - Emits `start_solo_test` socket event with the constructed deck. - - On success, saves room ID to `localStorage` and navigates to the Lobby tab using `onGoToLobby`. - - Added "Test Solo" button to the UI next to "Play Online". -- **`LobbyManager.tsx`**: Existing `rejoin_room` logic (triggered on mount via `localStorage`) handles picking up the active session. - -### Server-Side Updates -- **`src/server/index.ts`**: - - Updated `rejoin_room` handler to emit `game_update` if the room status is `playing`. This ensures that when the client navigates to the lobby and "rejoins" the solo session, the game board is correctly rendered. - -## User Flow -1. User generates packs in Cube Manager. -2. User clicks "Test Solo". -3. System builds a random deck and creates a solo room on the server. -4. UI switches to "Online Lobby" tab. -5. Lobby Manager detects the active session and loads the Game Room. -6. User plays the game. -7. User can click "Leave Room" icon in the sidebar to return to the Lobby creation screen. diff --git a/docs/development/devlog/2025-12-17-165500_update_deck_autofill.md b/docs/development/devlog/2025-12-17-165500_update_deck_autofill.md deleted file mode 100644 index dda3d40..0000000 --- a/docs/development/devlog/2025-12-17-165500_update_deck_autofill.md +++ /dev/null @@ -1,18 +0,0 @@ -# Update Deck Auto-Fill Logic - -## Request -The user requested that the "Auto-Fill" (Add Lands) button in the Deck Builder behave exactly like clicking individual lands in the Land Station. Specifically, lands should be added as individual card entries in the deck list so they can be viewed and removed one by one, rather than just updating a counter. - -## Implementation Plan -1. Modify `applySuggestion` function in `src/client/src/modules/draft/DeckBuilderView.tsx`. -2. Check if `availableBasicLands` is populated (indicating the graphical Land Station is active). -3. If active, iterate through the suggested land counts. -4. For each count, find the corresponding land card object in `availableBasicLands`. -5. Generate unique card objects (with unique IDs) for each land instance, replicating the logic of `addLandToDeck`. -6. Add these new land objects to the `deck` state. -7. Retain the old counter-based logic as a fallback if `availableBasicLands` is empty. - -## Status -- [x] Analyzed `DeckBuilderView.tsx` to understand current `applySuggestion` vs `addLandToDeck` logic. -- [x] Refactored `applySuggestion` to implement the new behavior. -- [x] Verified ID generation and state updates match existing patterns. diff --git a/docs/development/devlog/2025-12-17-170000_customizable_deck_builder.md b/docs/development/devlog/2025-12-17-170000_customizable_deck_builder.md deleted file mode 100644 index 6e57b1f..0000000 --- a/docs/development/devlog/2025-12-17-170000_customizable_deck_builder.md +++ /dev/null @@ -1,55 +0,0 @@ -# Customizable Deck Builder Layout - -## Request -The user wants to customize the Deck Builder interface with the following features: -1. **Layout Modes**: - * **Vertical View (Default)**: The current 3-column layout ([Zoom] | [Pool] | [Deck + Lands]). - * **Horizontal View**: A new layout where Pool is above the Deck. Land Station should be to the left of the Card Pool in this mode. -2. **Land Station Updates**: - * Remove "(Unlimited)" text. - * Increase container height. - * Integrate proper Land Advisor into the Land Station container to save space. - -## Design -### New Layout State -- State: `layout: 'vertical' | 'horizontal'` -- Toggle: A button group or switch to change layouts. - -### Component Structure -I will extract the core sections into render functions or variables to move them around easily. -- `renderZoomSidebar()` -- `renderPool()` -- `renderDeck()` -- `renderLandStation()` (This will now include the Land Advisor inside it) - -### Horizontal Layout Grid -Structure: -``` -[Zoom Sidebar (Fixed Left)] | [Main Content (Flex Column)] - | - |-- [Top Row (Flex Row)] - | |-- [Land Station (width fixed or flex)] - | |-- [Pool (Flex 1)] - | - |-- [Bottom Row (Flex 1)] - |-- [Deck] -``` - -### Vertical Layout Grid (Current) -Structure: -``` -[Zoom Sidebar] | [Pool] | [Deck + Land Station] -``` -*Note: In current layout, Land Station is stacked vertically with Deck in the 3rd column. User is fine with "exactly how is it now" for vertical.* - -### Land Station Refactoring -- Combine `Advice Panel` and `Land Station` div. -- Remove `(Unlimited)`. -- Increase height (e.g., `h-64` or `min-h-[200px]`). - -## Implementation Steps -1. Read `DeckBuilderView.tsx` (already read). -2. Refactor to extract render helper functions for clear modularity. -3. Add `layout` state and toggle UI. -4. Implement CSS grids/flex layouts for both modes. -5. Modify Land Station to include Advisor and styling updates. diff --git a/docs/development/devlog/2025-12-17-183000_restore_stack_hover.md b/docs/development/devlog/2025-12-17-183000_restore_stack_hover.md deleted file mode 100644 index 40c6dac..0000000 --- a/docs/development/devlog/2025-12-17-183000_restore_stack_hover.md +++ /dev/null @@ -1,16 +0,0 @@ -# Restore Hover Magnified Card for Stack View - -## Task -Restore the hover magnified card functionality for the stacked view in the pack generation UI, while ensuring it remains disabled for the deck building UI. - -## Changes -- Modified `src/client/src/components/StackView.tsx`: - - Imported `CardHoverWrapper`. - - Added `disableHoverPreview` prop (default `false`). - - Wrapped card elements with `CardHoverWrapper`, passing `preventPreview` based on the new prop and card width. -- Modified `src/client/src/modules/draft/DeckBuilderView.tsx`: - - Passed `disableHoverPreview={true}` to `StackView` to maintain existing behavior for the deck builder (which uses a dedicated sidebar preview). - -## Outcome -- Pack Generation UI (Cube Manager) now shows floating previews for cards in Stack View. -- Deck Builder UI remains unchanged (no double previews). diff --git a/docs/development/devlog/2025-12-17-183500_draft_ui_upgrade.md b/docs/development/devlog/2025-12-17-183500_draft_ui_upgrade.md deleted file mode 100644 index 542c29a..0000000 --- a/docs/development/devlog/2025-12-17-183500_draft_ui_upgrade.md +++ /dev/null @@ -1,16 +0,0 @@ -# Draft Cards Picker UI Update - -## Task -Update the `DraftView` to implement a 3D-flipping card preview sidebar (consistent with the Deck Builder) and ensure foil cards are rendered correctly in both the preview and the main selection grid. - -## Changes -- Modified `src/client/src/modules/draft/DraftView.tsx`: - - Imported `FoilOverlay` component. - - Defined `normalizeCard` helper to standardise card object structure (handling images and finish). - - Added `displayCard` state to persist card details during the flip animation. - - Replaced the previous fade-in sidebar with the 3D perspective flip container from `DeckBuilderView`. - - Updated the card rendering loop in `activePack` to use `normalizeCard` and conditionally render `FoilOverlay` and foil-specific styles (purple glow, badges). - -## Outcome -- **Sidebar**: Now features a persistent 3D flip animation. When hovering a card, it flips to show the front; when not hovering, it shows the card back (`/images/back.jpg`). -- **Foil Support**: Start using `FoilOverlay` for both the main draft grid and the sidebar preview, providing visual consistency for premium cards. diff --git a/docs/development/devlog/2025-12-17-184000_fix_draft_pool_ui.md b/docs/development/devlog/2025-12-17-184000_fix_draft_pool_ui.md deleted file mode 100644 index 33887c0..0000000 --- a/docs/development/devlog/2025-12-17-184000_fix_draft_pool_ui.md +++ /dev/null @@ -1,13 +0,0 @@ -# Fix Draft UI Issues - -## Task -Fix bugs in the Draft Pick UI related to the "Your Pool" section. - -## Changes -- Modified `src/client/src/modules/draft/DraftView.tsx`: - - **Resize Handle Fix**: Updated the resize event listeners (`mousemove`, `mouseup`) to be attached to `document` instead of `window`. This ensures the resize action continues smoothly even if the mouse leaves the browser window or moves rapidly over iframes/other elements that might swallow events. - - **Remove Hover Effect**: Removed the `hover:-translate-y-10` class from the drafted card items in the bottom pool view. The cards will now remain stationary on hover, as requested. - -## Outcome -- The pool resizing experience is now consistent and does not lose focus when dragging quickly. -- Cards in the "Your Pool" strip no longer jump up when hovered, providing a stable viewing experience. diff --git a/docs/development/devlog/2025-12-17-185000_draft_view_layout.md b/docs/development/devlog/2025-12-17-185000_draft_view_layout.md deleted file mode 100644 index a42de22..0000000 --- a/docs/development/devlog/2025-12-17-185000_draft_view_layout.md +++ /dev/null @@ -1,19 +0,0 @@ -# 2025-12-17 Draft View Layout Implementation - -## Objective -Implement vertical and horizontal layout selection for the Draft View "Your Pool" section, similar to the Deck Builder. Ensure the pool section does not overlap with the card preview sidebar and shares the width with the active pack section in vertical mode. - -## Changes -1. **Modified `src/client/src/modules/draft/DraftView.tsx`**: - * Added `layout` state ('vertical' | 'horizontal'). - * Added layout toggle buttons (`Columns`, `LayoutTemplate` icons) to the header toolbar. - * Refactored the main content area to utilize a `flex` container that wraps both the Active Pack and the Pool sections. - * **Vertical Layout**: Renders Pack and Pool side-by-side (50/50 split) within the content area, ensuring `Pool` is to the right of the `ZoomSidebar` and does not overlap. - * **Horizontal Layout**: Retains the original "Pool at Bottom" behavior but moves the Pool section *inside* the content area flex container to respect the sidebar boundary. - * Updated `PoolCardItem` to support a vertical grid layout style when in vertical mode. - -## Verification -* **Layout Switching**: Confirmed logic for switching between vertical (row) and horizontal (column) flex directions. -* **Sidebar Overlap**: The Pool section is now a sibling of the Pack section and both are children of the container adjacent to the fixed-width Sidebar. Use of `flex-1 flex overflow-hidden` ensures proper containment. -* **Resizing**: Preserved resize functionality for the horizontal layout (pool height). -* **Visual Consistency**: Used similar styling and icons as the Deck Builder. diff --git a/docs/development/devlog/2025-12-18-004109_fix_cube_sidebar_scrolling.md b/docs/development/devlog/2025-12-18-004109_fix_cube_sidebar_scrolling.md deleted file mode 100644 index 4905124..0000000 --- a/docs/development/devlog/2025-12-18-004109_fix_cube_sidebar_scrolling.md +++ /dev/null @@ -1,14 +0,0 @@ -# Fix Cube Manager Sidebar Scrolling on Tablets - -## Context -The user reported an issue on small tablet screens where the sticky sidebar in the Pack Generation UI (Cube Manager) cannot be scrolled to the bottom. The `max-height` of the sidebar was set to `100vh - 2rem`, which exceeds the actual visible viewport height when accounting for the application header (and potentially browser bars), causing the bottom of the sidebar (containing the critical "Generate Packs" button) to be clipped and inaccessible without scrolling the main page. - -## Changes -- Modified `src/client/src/modules/cube/CubeManager.tsx` to adjust the sidebar `max-height`. -- Changed `lg:max-h-[calc(100vh-2rem)]` to `lg:max-h-[calc(100vh-10rem)]`. -- This calculation (~ 10rem) accounts for the header height (approx 5-6rem), footer height (approx 2.5rem), and margins, ensuring the sidebar fits completely within the visible viewport. -- This ensures the `overflow-y-auto` property on the sidebar triggers correctly, allowing autonomous scrolling of the configuration panel regardless of the main page scroll position. - -## Verification -- Verified layout structure in `App.tsx` and proper nesting. -- The change applies to `lg` screens (desktop and horizontal tablet), where the sidebar is displayed as a sticky column. diff --git a/docs/development/devlog/2025-12-18-004600_pwa_install_prompt.md b/docs/development/devlog/2025-12-18-004600_pwa_install_prompt.md deleted file mode 100644 index 744cc22..0000000 --- a/docs/development/devlog/2025-12-18-004600_pwa_install_prompt.md +++ /dev/null @@ -1,23 +0,0 @@ -# PWA Install Prompt Implementation Plan - -## Objective -Implement a user interface that prompts the user to install the application as a PWA on supported devices (primarily Android/Chrome). - -## Tasks -1. Create `src/client/src/components/PWAInstallPrompt.tsx` that: - - Listens for `beforeinstallprompt` event. - - Displays a custom UI (toast/banner) when the event is captured. - - Calls `prompt()` on the event object when the user clicks "Install". - - Handles the user's choice. -2. Integrate `PWAInstallPrompt` into `App.tsx`. -3. Verify `vite.config.ts` PWA settings (already done, looks good). - -## Implementation Details -- The component will use a fixed position styling (bottom right/center) to be noticeable but not blocking. -- It will use existing design system (Tailwind). - -## Status -- [x] Create Component -- [x] Integrate into App -- [x] Update Config -- **Completed**: 2025-12-18 diff --git a/docs/development/devlog/2025-12-18-005000_fix_pwa_prompt.md b/docs/development/devlog/2025-12-18-005000_fix_pwa_prompt.md deleted file mode 100644 index de1c8fb..0000000 --- a/docs/development/devlog/2025-12-18-005000_fix_pwa_prompt.md +++ /dev/null @@ -1,33 +0,0 @@ -# Fix PWA Install Prompt Implementation Plan - -## Objective -Ensure the PWA install prompt appears reliably on mobile devices, addressing potential issues with event timing, iOS compatibility, and explicit Service Worker registration. - -## Root Causes to Address -1. **Late Event Listener**: The `beforeinstallprompt` event might fire before the React component mounts. We need to capture it globally as early as possible. -2. **Missing Service Worker Registration**: While `vite-plugin-pwa` can auto-inject, explicit registration in `main.tsx` ensures it's active and handles updates. -3. **iOS Compatibility**: iOS does not support `beforeinstallprompt`. We must detect iOS and show specific "Share -> Add to Home Screen" instructions. -4. **Secure Context**: PWA features require HTTPS. While we can't force this on the user's network, we can ensure the app behaves best-effort and maybe warn if needed (skipped for now to avoid noise, focusing on logical fixes). - -## Tasks -1. **Update `src/client/src/main.tsx`**: - - Import `registerSW` from `virtual:pwa-register`. - - Add a global `window` event listener for `beforeinstallprompt` immediately upon script execution to capture the event. - - Expose the captured event on `window` (or a global store) so the React component can consume it. -2. **Update `src/client/src/components/PWAInstallPrompt.tsx`**: - - Check `window.deferredInstallPrompt` (or similar) on mount. - - Add User Agent detection for iOS (iPhone/iPad/iPod). - - If iOS, display a custom "Add to Home Screen" instruction banner. - - If Android/Desktop, use the captured prompt. -3. **Docs**: Update devlog. - -## Technical Details -- **Global Property**: `window.deferredInstallPrompt` -- **iOS Detection**: Regex on `navigator.userAgent` looking for `iPhone|iPad|iPod` (and not `MSStream`). - -## Status -- [x] Register SW explicitly in main.tsx -- [x] Capture `beforeinstallprompt` globally -- [x] Add iOS specific UI -- **Completed**: 2025-12-18 - diff --git a/docs/development/devlog/2025-12-18-005300_persist_pwa_dismissal.md b/docs/development/devlog/2025-12-18-005300_persist_pwa_dismissal.md deleted file mode 100644 index 8b54a20..0000000 --- a/docs/development/devlog/2025-12-18-005300_persist_pwa_dismissal.md +++ /dev/null @@ -1,20 +0,0 @@ -# Persist PWA Prompt Dismissal - -## Objective -Ensure the PWA install prompt honors the user's previous interactions. If the user dismisses the prompt (clicks X) or initiates the install flow, the prompt should not appear again in subsequent sessions. - -## Implementation Details -1. **Storage**: Use `localStorage` key `pwa_prompt_dismissed` (value: 'true'). -2. **Logic Update** in `PWAInstallPrompt.tsx`: - - On mount: Check if `localStorage.getItem('pwa_prompt_dismissed') === 'true'`. If so, return `null` immediately. - - On Dismiss (X click): Set `localStorage.setItem('pwa_prompt_dismissed', 'true')` and hide UI. - - On Install Click: Set `localStorage.setItem('pwa_prompt_dismissed', 'true')` immediately. Even if they cancel the native dialog, we respect their choice to have interacted with it once. (Or should we? The user said "after a use choice". I will assume entering the flow counts). - -## Refinements -- We might want to allow re-prompting after a long time (e.g., storing a timestamp), but the request is simple: "do not show... after a use choice". I will stick to simple boolean persistence for now. - -## Status -- [x] Add logic to check/set `pwa_prompt_dismissed` -- [x] Update dismissal (X button) logic -- [x] Update install logic -- **Completed**: 2025-12-18 diff --git a/docs/development/devlog/2025-12-18-005739_create_favicon.md b/docs/development/devlog/2025-12-18-005739_create_favicon.md deleted file mode 100644 index ca9bc5b..0000000 --- a/docs/development/devlog/2025-12-18-005739_create_favicon.md +++ /dev/null @@ -1,10 +0,0 @@ -# Plan: Create Favicon - -## Objective -Create and integrate a high-quality favicon for the MTG Draft Maker application, adhering to the "Dark Gaming UI" aesthetic. - -## Steps -1. **Generate Favicon**: Use image generation to create a sleek, modern icon representing a card draft or pack, using the app's color palette (Emerald/Purple on Dark). -2. **Save Asset**: Save the generated image to `src/client/public/favicon.png`. -3. **Update HTML**: Add the `` tag to `src/client/index.html`. -4. **Verify**: Ensure the favicon is correctly referenced. diff --git a/docs/development/devlog/2025-12-18-012500_mobile_touch_preview.md b/docs/development/devlog/2025-12-18-012500_mobile_touch_preview.md deleted file mode 100644 index 3f3c5d1..0000000 --- a/docs/development/devlog/2025-12-18-012500_mobile_touch_preview.md +++ /dev/null @@ -1,15 +0,0 @@ -# 2025-12-18 01:25:00 - Mobile Touch Prevention on Pack List - -## User Request -The user requested to disable the hover-to-preview functionality on touch screens in the draft management pack list and instead use long-press to open the preview, matching the behavior on small mobile screens. - -## Implementation Details -Modified `CardPreview.tsx` to update the `CardHoverWrapper` component. -- Changed `isMobile` detection logic from a simple `window.innerWidth < 1024` check to a more robust check that includes `window.matchMedia('(pointer: coarse)')`. -- Removed `(hover: none)` from the check to ensure devices that report hover capability (like some tablets with styluses) but are primarily touch-based are still treated as mobile. -- This ensures that devices with touch capabilities (like tablets) are treated as "mobile" by the component, disabling the default hover behavior and enabling the long-press gesture for card previews. -- This change affects `CubeManager` (Pack List) and any other component using `CardHoverWrapper` (e.g., `StackView` inside `PackCard`). - -## Risk Handling -- Verified that `DraftView` uses its own touch logic (`useCardTouch`) so it remains unaffected (though it behaves similarly). -- Ensures that touch laptops (which might support hover) are not aggressively forced into mobile mode unless they match `hover: none` (which usually targets tablets/phones). This tries to preserve mouse functionality where available, although the user's request was specific to "touch screens". The `hover: none` media query is the standard way to detect touch-primary devices. diff --git a/docs/development/devlog/2025-12-18-013000_minimize_slider_defaults.md b/docs/development/devlog/2025-12-18-013000_minimize_slider_defaults.md deleted file mode 100644 index e995f0d..0000000 --- a/docs/development/devlog/2025-12-18-013000_minimize_slider_defaults.md +++ /dev/null @@ -1,16 +0,0 @@ -# Work Plan - Set Default Slider Values to Minimum - -## Request -Set the default value for card size sliders to their minimum setting across all views: -1. Cube Manager (Draft Management) -2. Draft View (Online Draft Pick) -3. Deck Builder - -## Changes -- **CubeManager.tsx**: Changed default `cardWidth` from `140` to `100`. -- **DraftView.tsx**: Changed default `cardScale` from `0.7` to `0.5`. -- **DeckBuilderView.tsx**: Changed default `cardWidth` from `150` to `100`. - -## Verification -- Verified that the new default values match the `min` attribute of the respective range inputs. -- Verified that no other sliders exist in the codebase. diff --git a/docs/development/devlog/2025-12-18-014500_deck_builder_touch.md b/docs/development/devlog/2025-12-18-014500_deck_builder_touch.md deleted file mode 100644 index 0c0c939..0000000 --- a/docs/development/devlog/2025-12-18-014500_deck_builder_touch.md +++ /dev/null @@ -1,20 +0,0 @@ -# Work Plan - Deck Builder Touch Interaction Updates - -## Request -1. Change "Deck" zone name to "Library" in the UI. -2. Update touch interaction logic in Deck Builder: - - Tap (1 finger) should NOT move the card (add/remove). - - Tap (1 finger) should show the Card Preview (like in Draft Pick). - - Drag and Drop remains the method to move cards on touch devices. - -## Changes -- **DeckBuilderView.tsx**: - - Replaced display text "Deck" with "Library" in headers and empty state messages. - - Updated `ListItem`, `DeckCardItem`, and `StackView` `onClick` handlers. - - Implemented `window.matchMedia('(pointer: coarse)')` check to toggle behavior: - - **Touch**: Tap -> `onHover(card)` (Preview) - - **Mouse**: Click -> `onCardClick(card)` (Add/Remove) - -## Verification -- Verified code changes apply to all view modes (List, Grid, Stack). -- Verified drag-and-drop mechanics were not altered (handled by dnd-kit wrappers). diff --git a/docs/development/devlog/2025-12-18-020000_stack_sorting_sliders.md b/docs/development/devlog/2025-12-18-020000_stack_sorting_sliders.md deleted file mode 100644 index a95ea3e..0000000 --- a/docs/development/devlog/2025-12-18-020000_stack_sorting_sliders.md +++ /dev/null @@ -1,34 +0,0 @@ -# Work Plan - Stack View Sorting & Slider Updates - -## Request -1. **Slider Adjustment**: Decrease the scale of sliders globally. - * New Min (0%) should be smaller (~50% of previous min?). - * New Max (100%) should be equivalent to old 50%. -2. **Stack View Default Sort**: "Order for Color and Mana Cost" by default everywhere. -3. **Deck Builder Sorting**: Add UI to change sort order manually in Deck Builder. - -## Changes -- **StackView.tsx**: - - Refactored to support dynamic `groupBy` logic (Type, Color, CMC, Rarity). - - Implemented categorization logic for Color, CMC, and Rarity. - - Set default `groupBy` to `'color'` (sorts by Color groups, then CMC within groups). - - Fixed syntax errors from previous edit. - -- **DeckBuilderView.tsx**: - - Added `groupBy` state (default `'color'`). - - Added "Sort:" dropdown to toolbar when in Stack View. - - Updated `CardsDisplay` to pass sorting preferences. - - Updated Slider range to `min="60" max="200"` (Default `60`). - -- **CubeManager.tsx**: - - Updated Slider range to `min="60" max="200"`. - - Updated default `cardWidth` to `60`. - -- **DraftView.tsx**: - - Updated Slider range to `min="0.35" max="1.0"`. - - Updated default `cardScale` to `0.35`. - -## Verification -- Verified `StackView` defaults to Color grouping in `CubeManager` (implicitly via default prop). -- Verified Deck Builder has sorting controls. -- Verified all sliders allow for much smaller card sizes. diff --git a/docs/development/devlog/2025-12-18-023000_lobby_ui_update.md b/docs/development/devlog/2025-12-18-023000_lobby_ui_update.md deleted file mode 100644 index 46dbca0..0000000 --- a/docs/development/devlog/2025-12-18-023000_lobby_ui_update.md +++ /dev/null @@ -1,28 +0,0 @@ -# Work Plan - Lobby & Chat UI Overhaul and Notifications - -## Request -1. **Lobby/Chat Sidebar**: Refactor to be collapsible on the right edge. - - Add floating/modal panel for Lobby and Chat content. - - Remove fixed right column layout. -2. **Notifications**: Implement toast notifications for player events (Join, Leave, Disconnect). - - Add setting to Enable/Disable notifications (persisted). -3. **Deck Builder**: Update "Full Card" display trigger to new slider range (50% = 130px). - -## Changes -- **DeckBuilderView.tsx**: - - Updated `useArtCrop` logic: `cardWidth < 130` (was 200). - -- **GameRoom.tsx**: - - Refactored layout: Added `activePanel` state. - - Created `useEffect` hook with `prevPlayersRef` to detect changes and trigger toasts. - - Added "Notifications On/Off" toggle in Lobby panel. - - Implemented floating side panel UI for desktop. - - Updated mobile view (kept separate mobile tab logic but ensured layout stability). - -- **Toast.tsx**: - - Added `'warning'` type support for amber-colored alerts (Player Left). - -## Verification -- Verified `ref` based diffing logic for notifications. -- Verified persistence of notification settings in `localStorage`. -- checked `Toast` type definition update. diff --git a/docs/development/devlog/2025-12-18-024000_preview_threshold.md b/docs/development/devlog/2025-12-18-024000_preview_threshold.md deleted file mode 100644 index 94c8f5c..0000000 --- a/docs/development/devlog/2025-12-18-024000_preview_threshold.md +++ /dev/null @@ -1,12 +0,0 @@ -# Work Plan - Card Preview Threshold Update - -## Request -- **Card Preview**: Change the trigger to show the full card to the what now is the new 50% (130px) instead of 200px. - -## Changes -- **PackCard.tsx**: Updated logic to `cardWidth < 130` for art crop usage and `cardWidth >= 130` for hover preview prevention. -- **StackView.tsx**: Updated logic to `cardWidth < 130` and `cardWidth >= 130` respectively. - -## Verification -- Verified code changes in `PackCard.tsx` and `StackView.tsx` via `replace_file_content` outputs. -- `DeckBuilderView.tsx` was already updated in previous step. diff --git a/docs/development/devlog/2025-12-18-030000_ui_enhancements.md b/docs/development/devlog/2025-12-18-030000_ui_enhancements.md deleted file mode 100644 index 7bda0dc..0000000 --- a/docs/development/devlog/2025-12-18-030000_ui_enhancements.md +++ /dev/null @@ -1,28 +0,0 @@ -# Work Plan - Deck Builder & Draft UI Enhancements - -## Request -1. **Deck Builder Stack DnD**: Enable card drag and drop for the stacked view in Deck Builder. -2. **Custom Sort Dropdown**: Use a custom graphic dropdown list instead of browser default for sorting. -3. **Resizable Layouts**: Make library/preview resizeable in Deck Builder, and selected pool/preview resizeable in Draft UI. - -## Changes -- **StackView.tsx**: Added `renderWrapper` prop to allow parent components to wrap card items (e.g. with `DraggableCardWrapper`). -- **DeckBuilderView.tsx**: - - Implemented `sortDropdownOpen` state and custom UI for the "Sort" dropdown. - - Added resizing state (`sidebarWidth`, `poolHeightPercent`) and mouse event handlers. - - Applied dynamic styles to Sidebar and Pool/Deck zones. - - Passed `DraggableCardWrapper` to `StackView` via the new `renderWrapper` prop. -- **DraftView.tsx**: - - Added resizing state (`sidebarWidth`, `poolHeight`) and mouse event handlers. - - Applied dynamic styles to Sidebar and Pool Droppable area. - - Fixed syntax error introduced during refactoring. - -## Verification -- **Deck Builder**: - - Verify cards in Stack View can be dragged. - - Verify "Sort" dropdown is custom styled. - - Verify Sidebar width can be adjusted. - - Verify Pool/Library split can be adjusted (in horizontal mode especially). -- **Draft UI**: - - Verify Sidebar width can be adjusted. - - Verify Selected Pool height can be adjusted. diff --git a/docs/development/devlog/2025-12-18-033000_resize_optimization.md b/docs/development/devlog/2025-12-18-033000_resize_optimization.md deleted file mode 100644 index ad181f9..0000000 --- a/docs/development/devlog/2025-12-18-033000_resize_optimization.md +++ /dev/null @@ -1,27 +0,0 @@ -# Work Plan - Optimize Resize Performance - -## Request -The user reported that the resize functionality was laggy, slow, and inconsistent. - -## Changes -- **Refactoring Strategy**: - - Removed React state updates from the `mousemove` event loop. - - Used `useRef` to track `sidebarWidth` and `poolHeight` values. - - Used `requestAnimationFrame` to throttle DOM updates directly during resizing. - - Only triggered React state updates (re-renders) on `mouseup`. - -- **DraftView.tsx**: - - Implemented `resizingState` ref. - - Modified `handleMouseDown` to initiate direct DOM resizing. - - Modified `onMouseMove` to update element styles directly. - - Modified `onMouseUp` to sync final size to React state. - - Applied refs to Sidebar and Pool resizing areas. - -- **DeckBuilderView.tsx**: - - Implemented identical ref-based + requestAnimationFrame resizing logic. - - Fixed several HTML nesting errors introduced during the complex refactoring process. - -## Verification -- **Performance**: Resizing should now be smooth (60fps) as it avoids React reconciliation during the drag. -- **Consistency**: The handle should no longer "slip" because the visual update is faster. -- **Persistence**: The final size is still saved to `state` (and thus `localStorage`) after release. diff --git a/docs/development/devlog/2025-12-18-034500_slider_optimization.md b/docs/development/devlog/2025-12-18-034500_slider_optimization.md deleted file mode 100644 index 6d23637..0000000 --- a/docs/development/devlog/2025-12-18-034500_slider_optimization.md +++ /dev/null @@ -1,27 +0,0 @@ -# Work Plan - Optimize Card Slider Performance - -## Request -The user reported that resize handlers (likely sliders) were still laggy. - -## Changes -- **DraftView.tsx**: - - Introduced `localCardScale` for immediate slider feedback. - - Used CSS Variable `--card-scale` on container to update card sizes entirely via CSS during drag. - - Deferred `cardScale` state update (which triggers React re-renders) to `onMouseUp`. - -- **DeckBuilderView.tsx**: - - Introduced `localCardWidth` for immediate slider feedback. - - Used CSS Variable `--card-width` on container. - - Updated `gridTemplateColumns` to use `var(--card-width)`. - - Deferred `cardWidth` state update to `onMouseUp`. - - Cleaned up duplicate state declarations causing lint errors. - -- **CubeManager.tsx**: - - Introduced `localCardWidth` and CSS Variable `--card-width`. - - Updated Grid layout to use CSS Variable. - - Deferred state update to `onMouseUp`. - -## Verification -- **Performance**: Slider dragging should now be 60fps smooth as it touches 0 React components during the drag, only updating a single CSS variable on the root container. -- **Persistence**: Releasing the slider saves the value to state and localStorage. -- **Logic**: complex logic like `useArtCrop` (which depends on specific widths) updates safely on release, preventing flicker or heavy recalculations during drag. diff --git a/docs/development/devlog/2025-12-18-040000_sidebar_resize_fix.md b/docs/development/devlog/2025-12-18-040000_sidebar_resize_fix.md deleted file mode 100644 index 9a54d40..0000000 --- a/docs/development/devlog/2025-12-18-040000_sidebar_resize_fix.md +++ /dev/null @@ -1,16 +0,0 @@ -# Work Plan - Fix Sidebar Resize Animation Lag - -## Request -The user reported that the left sidebar resize was laggy because of an animation. - -## Changes -- **DraftView.tsx**: - - Identified that `transition-all` class was present on the sidebar container. - - Removed `transition-all` class. This class forces the browser to interpolate the width over 300ms every time javascript updates it (60 times a second), causing severe visual lag and "fighting" between the cursor and the element. - - Verified that resize logic uses the previously implemented `requestAnimationFrame` + `ref` approach, which is optimal. - -- **DeckBuilderView.tsx**: - - Verified that no `transition` class was present on the corresponding sidebar element. - -## Verification -- **Performance**: Sidebar resizing should now be instant and track the mouse 1:1 without "slipping" or lag. diff --git a/docs/development/devlog/2025-12-18-041500_touch_resize.md b/docs/development/devlog/2025-12-18-041500_touch_resize.md deleted file mode 100644 index 80217bb..0000000 --- a/docs/development/devlog/2025-12-18-041500_touch_resize.md +++ /dev/null @@ -1,20 +0,0 @@ -# Work Plan - Touch Resize Implementation - -## Request -The user reported that resizing handles were not working on touchscreen devices. - -## Changes -- **DraftView.tsx**: - - Replaced `handleMouseDown`, `onMouseMove`, `onMouseUp` with unified `handleResizeStart`, `onResizeMove`, `onResizeEnd`. - - Added logic to detect `touches` in event object and extract `clientX`/`clientY` from the first touch point. - - Attached `onTouchStart` to sidebar and pool resize handles. - - Added `passive: false` to touch event listeners (via `useEffect` logic or direct attach) to call `e.preventDefault()`, preventing page scrolling while dragging. Note: Implemented in the handler function with `if (e.cancelable) e.preventDefault()`. - - Added `touch-none` utility class to resize handles to structurally prevent browser touch actions. - -- **DeckBuilderView.tsx**: - - Implemented the exact same unified handler logic as DraftView. - - Updated both Sidebar (vertical) and Pool (horizontal) resize handles with `onTouchStart`. - -## Verification -- **Touch**: Dragging handles on a touchscreen (mobile/tablet) should now resize the panels smoothly. -- **Mouse**: Mouse interaction remains unchanged and performant (using `requestAnimationFrame`). diff --git a/docs/development/devlog/2025-12-18-042500_pool_card_sizing.md b/docs/development/devlog/2025-12-18-042500_pool_card_sizing.md deleted file mode 100644 index a57160e..0000000 --- a/docs/development/devlog/2025-12-18-042500_pool_card_sizing.md +++ /dev/null @@ -1,13 +0,0 @@ -# Work Plan - Fix Pool Card Sizing - -## Request -The user reported that cards in the horizontal pool list were "enormous" after previous changes. - -## Changes -- **DraftView.tsx**: - - Reverted the `height` class of `PoolCardItem` images (in horizontal mode) from `h-full` to `h-[90%]`. - - `h-full` was causing the image to expand uncontrollably in some flex layouts, ignoring the parent container's constraints. - - `h-[90%]`, combined with `items-center` on the parent container, properly constrains the image to fit within the strip, maintaining aspect ratio via `w-auto`. - -## Verification -- **Visuals**: Cards in the bottom "Your Pool" strip should now cleanly fit within the resizeable panel, with a small vertical margin, instead of overflowing or appearing excessively large. diff --git a/docs/development/devlog/2025-12-18-043500_pool_sizing_final.md b/docs/development/devlog/2025-12-18-043500_pool_sizing_final.md deleted file mode 100644 index 7bda281..0000000 --- a/docs/development/devlog/2025-12-18-043500_pool_sizing_final.md +++ /dev/null @@ -1,31 +0,0 @@ -# Work Plan - Finalize Pool Card Sizing - -## Request -The user reported: "cards inside the 'your pool' have not consistent sizes ... and resizing it's height does not change card sizes. card height needs to match the your pool panel size". - -## Analysis -The previous logic using `items-center` on the parent and `h-full`/`h-90%` on the child likely led to a broken flexbox behavior where children calculated their own intrinsic height or got stuck at an initial height, and `transition-all` might have added to the confusion or stickiness. - -## Changes -- **DraftView.tsx**: - - Removed `transition-all` from both `PoolDroppable` and `PoolCardItem`. Transitions on layout containers cause jank during drag resize and can block instant reflow. - - Updated horizontal pool scrolling container: - - Removed `items-center`. The default behavior aligns items to start, but since we want `h-full` to work, the container just needs to fill space. - - Changed padding to `pb-2 pt-2` (balanced) instead of `pb-4`. - - Updated `PoolCardItem` (Horizontal): - - `className`: Added `h-full`, **removed `items-center`** (moved to centered justify content if needed, but flex default with no items-center is fine). Added `aspect-[2.5/3.5]` to help width calculation. Added `p-2` padding directly to the wrapper to handle spacing, allowing image to be `h-full` within that padded box. - - Image: Changed to `h-full w-auto object-contain`. Removed `max-h-full` and `h-[90%]`. - -## Result -- The `poolRef` div resizes via DOM. -- `PoolDroppable` (flex-1) fills it. -- Scroll container (flex-1) fills it. -- `PoolCardItem` wrapper (h-full) fills 100% of the Scroll container height. -- `PoolCardItem` wrapper padding (`p-2`) creates a safe zone. -- `img` (h-full) fills 100% of the wrapper's content box (calculated as `Total Height - Padding`). -- This guarantees the image height tracks the panel height 1:1. - -## Verification -- Dragging the pool resize handle should now smoothly resize the cards in real-time. -- Cards should never be "too big" (overflowing) because they are strictly contained by `h-full` inside the overflow-hidden parents. -- Cards should respect aspect ratio. diff --git a/docs/development/devlog/2025-12-18-044500_pool_overflow_fix.md b/docs/development/devlog/2025-12-18-044500_pool_overflow_fix.md deleted file mode 100644 index ab8276f..0000000 --- a/docs/development/devlog/2025-12-18-044500_pool_overflow_fix.md +++ /dev/null @@ -1,13 +0,0 @@ -# Work Plan - Strict Overflow Constraints for Pool Panel - -## Request -The user persists that cards overflow because they are "full size" and do not resize. - -## Changes -- **DraftView.tsx**: - - Added `overflow-hidden` to the root `poolRef` div. This ensures that even if internal contents *try* to be larger, they are clipped, and more importantly, it forces flex children to respect the parent boundary in some browser rendering engines. - - Added `min-h-0` to `PoolDroppable` and the inner scroll container. In Flexbox columns, children do not shrink below their content size by default. `min-h-0` effectively overrides this, forcing the container to shrink to the available flex space (which is effectively `poolRef` height minus header). - - This combination guarantees that the scroll container's `height` is exactly calculated based on the parent, so `h-full` on the card images resolves to the correct, resized pixel value. - -## Verification -- **Visuals**: Resizing the pool panel should now force the cards to shrink or grow in real-time without overflowing or getting stuck at a large size. diff --git a/docs/development/devlog/2025-12-18-050000_resize_persistence.md b/docs/development/devlog/2025-12-18-050000_resize_persistence.md deleted file mode 100644 index 4c1b470..0000000 --- a/docs/development/devlog/2025-12-18-050000_resize_persistence.md +++ /dev/null @@ -1,18 +0,0 @@ -# Work Plan - Persist Resize State - -## Request -The user wants resized areas (sidebar and pool) to be remembered (persisted) so they reopen with the same sizes. - -## Changes -- **DraftView.tsx**: - - Updated initialization of `sidebarWidth` state to read from `localStorage.getItem('draft_sidebarWidth')`. - - Added `useEffect` to save `sidebarWidth` to `localStorage` whenever it changes. - - Verified `poolHeight` persistence logic already exists. - -- **DeckBuilderView.tsx**: - - Updated initialization of `sidebarWidth` and `poolHeightPercent` to read from `localStorage` keys `deck_sidebarWidth` and `deck_poolHeightPercent`. - - Added `useEffect` hooks to persist both values to `localStorage`. - - Added `useEffect` to imports (fixed lint error). - -## Verification -- **Test**: Refreshing the page after resizing the sidebar or pool panel should restore the previous dimensions exactly. diff --git a/docs/development/devlog/2025-12-18-112633_resolve_413_errors.md b/docs/development/devlog/2025-12-18-112633_resolve_413_errors.md deleted file mode 100644 index 3170b69..0000000 --- a/docs/development/devlog/2025-12-18-112633_resolve_413_errors.md +++ /dev/null @@ -1,16 +0,0 @@ -# Resolve 413 Request Entity Too Large Errors - -## Objective -Fix the "413 Request Entity Too Large" errors occurring during large uploads or requests after application deployment. - -## Changes -1. **Helm Chart Configuration (`helm/mtg-draft-maker/values.yaml`)**: - * Added Nginx Ingress annotation `nginx.ingress.kubernetes.io/proxy-body-size: "0"` to disable the body size limit check at the ingress level. - -2. **Server Configuration (`src/server/index.ts`)**: - * Increased `maxHttpBufferSize` for Socket.IO to 1GB. - * Increased `express.json` body parser limit to 1000MB to support large JSON payloads (e.g., extensive card lists). - -## Verification -* **Infrastructure**: Ensure the application is redeployed with the updated Helm chart for the ingress annotation to take effect. -* **Application**: Verify that large payloads can be sent to the server without triggering 413 errors. diff --git a/docs/development/devlog/2025-12-18-184500_mtg_engine_and_ux_archived_plan.md b/docs/development/devlog/2025-12-18-184500_mtg_engine_and_ux_archived_plan.md deleted file mode 100644 index e634cd9..0000000 --- a/docs/development/devlog/2025-12-18-184500_mtg_engine_and_ux_archived_plan.md +++ /dev/null @@ -1,154 +0,0 @@ -# Devlog: MTG Engine & UX Implementation Plan (Archived) - -*This document was originally the `mtg-engine-and-ux.md` plan. It has been archived here as a record of the architecture and task breakdown used to build the strict rules engine and high-velocity UX.* - ---- - -# Implementation Plan: MTG Rules Engine & High-Velocity UX - -## Objective -Implement a strict Magic: The Gathering rules engine (Backend) and a "Rich Input" high-velocity user experience (Frontend). The goal is to enforce 100% of the Comprehensive Rules on the server while allowing fluid, gesture-based actions on the client. - -**Reference:** MagicCompRules 20251114.txt - ---- - -## PART 1: THE RULES ENGINE (Server-Side Logic) - -### A. Game Setup & Initialization (CR 103) -The engine must execute this sequence automatically before the first turn: - -1. **Deck Validation**: Verify decks meet format requirements (e.g., 60 cards min). -2. **Life Initialization**: Set Life Totals to 20. -3. **The Mulligan Process (CR 103.5)**: - - **Initial Draw**: Both players draw 7 cards. - - **Decision Loop**: Prompt players in turn order: "Keep Hand" or "Mulligan". - - **Execution**: If Mulligan, shuffle hand into library and draw 7 new cards. - - **London Rule**: For each Mulligan (N), user must select N cards to bottom. - - **Concurrency**: Decisions sequential, Shuffles/Draws simultaneous. - -### B. The Turn Structure State Machine (CR 500) -Strict phase cycle. Priority (CR 117) must be passed by both players to advance. - -1. **Beginning Phase (CR 501)** - - **Untap Step**: AP untaps all permanents. No Priority. - - **Upkeep Step**: Triggers go on stack. AP Priority. - - **Draw Step**: AP draws. Triggers. AP Priority. - -2. **Pre-Combat Main Phase (CR 505)** - - AP may Play Land (Special Action, 1/turn, Stack empty). - - AP may Cast Sorcery/Creature/Artifact/Enchantment/Planeswalker. - -3. **Combat Phase (CR 506)** - - **Start of Combat**: Triggers. Priority. - - **Declare Attackers (CR 508)**: - - AP selects attackers & targets (Player/Planeswalker). - - Engine validates restrictions & taps attackers. - - Triggers. AP Priority. - - **Declare Blockers (CR 509)**: - - DP assign blockers. - - Engine validates (Flying, Menace, etc.). - - Damage Ordering (if multi-blocked). - - Triggers. AP Priority. - - **Combat Damage (CR 510)**: - - AP assigns damage (Lethal to 1st, then rest). - - Damage dealt simultaneously. - - Priority Check. - - **End of Combat**: Priority Check. - -4. **Post-Combat Main Phase** - - Identical to Pre-Combat Main. - -5. **Ending Phase (CR 512)** - - **End Step**: Triggers. Priority. - - **Cleanup Step (CR 514)**: - - Discard to hand size. - - Remove marked damage. - - No Priority (unless trigger occurs). - -### C. The Interaction Core: Priority & The Stack (CR 405 & 117) -LIFO (Last-In, First-Out) Array. - -- **Priority Passing (CR 117.3d)**: Game advances only when all players pass on empty stack. -- **Response Window**: After cast, AP gets priority. If AP passes -> DP gets priority. If DP passes -> Resolve. -- **State-Based Actions (The Referee Check - CR 704)**: Checked BEFORE every priority gain. - - **Lethal Damage**: Damage >= Toughness -> Graveyard. - - **0 Toughness**: Toughness <= 0 -> Graveyard. - - **Legend Rule**: Duplicate legendary -> Controller chooses capture. - - **Aura Check**: Invalid attachment -> Graveyard. - -### D. Manual Mana Engine (CR 106) -- **Production**: Tap Land -> Add color to **Floating Pool**. -- **Spending**: Click symbol in pool to pay costs. -- **Emptying**: Pool empties at end of every Step/Phase. - -### E. Developer Notes & Edge Cases -- **Layer System (CR 613)**: Must implement 7-Layer system (Copy, Control, Text, Type, Color, Ability, P/T). -- **Token Generation**: Spawn game object with stats. -- **Failure States**: Insufficient mana -> Bounce, Warning Flash. - ---- - -## PART 2: THE "HIGH-VELOCITY" UX (Frontend Specification) - -### 1. The "Smart" Priority Button -Context-aware button (Bottom Right). -- **Green ("Pass")**: Stack empty. clicking passes/advances. -- **Orange ("Resolve")**: Stack has object. Click resolves top. -- **Red ("Damage/Block")**: Mandatory manual assignment waiting. -- **Blue ("Choice")**: Modal choice required. -- **"Yield" Toggle**: Auto-pass priority until End Step (unless response needed). - -### 2. Gesture Controls (Mouse/Touch) -- **Swipe-to-Tap**: Drag line across background/cards. Intersected lands toggle & add mana. -- **Combat Swipes**: - - Attack: Swipe Up/Forward. - - Cancel Attack: Swipe Down/Back. - - Block: Drag blocker onto attacker. -- **Targeting Tether**: Visual "rope" (Bezier curve) from source to target. - -### 3. Contextual Radial Menus -**Scenario**: User taps Dual Land. -- **Interaction**: Pie menu spawns under cursor. -- **Action**: Slide toward symbol to select. Minimal travel. - -### 4. Visualizing "The Stack" -Vertical list of tiles on screen edge. -- **Hover/Long-press**: Show source card. -- **Targeting**: Tiles must be valid targets for spells. - -### 5. The "Inspector" Overlay -Long-press/Right-click on card. -- **Display**: High-Res Art + Oracle Text. -- **Live Math**: Show Net Power/Toughness (Base + Layers). - ---- - -## Task Breakdown & Status - -### Backend (RulesEngine) -- [x] **Core Structures**: `StrictGameState`, Phase, Step Types. -- [x] **State Machine Baseline**: Phase advancement logic. -- [x] **Priority Logic**: Passing, resolving, resetting. -- [x] **Basic Actions**: Play Land, Cast Spell. -- [x] **Stack Resolution**: Resolving Spells to Zones. -- [x] **SBAs Implementation**: Basic (Lethal w/ Damage Marking, 0 Toughness, Legend). -- [x] **Advanced SBAs**: Aura Validity check. -- [x] **Manual Mana Engine**: Floating Pool Logic (Backend Support). -- [x] **Game Setup**: Mulligan (London), Deck Validation. -- [x] **Combat Phase Detail**: Declare Attackers/Blockers steps & validation (RulesEngine Logic). -- [x] **Layer System**: Implement 7-layer P/T calculation. -- [x] **Token Generation**: Backend `createToken` & Context Menu integration. - -### Frontend (High-Velocity UX) -- [x] **Game View**: Render State Types. -- [x] **Phase Strip**: Visual progress. -- [x] **Smart Button**: Basic States (Green/Orange/Red). -- [x] **Gesture Engine**: Swipe-to-Tap & Swipe-to-Attack. -- [x] **Stack Visualization**: Basic Component. -- [x] **Gesture Polish**: Combat Swipes, Targeting Tether. -- [x] **Manual Mana Engine**: Floating Pool Logic & UI. -- [x] **Mulligan UI**: Modal for Keep/Mull decisions. -- [x] **Smart Button Advanced**: "Yield" Toggle. -- [x] **Radial Menus**: Pie Menu for Dual Lands/Modes (Component Added). -- [x] **Inspector Overlay**: Live Math & Details. diff --git a/docs/development/devlog/2025-12-18-193855_implement_restart_game.md b/docs/development/devlog/2025-12-18-193855_implement_restart_game.md deleted file mode 100644 index 73fa107..0000000 --- a/docs/development/devlog/2025-12-18-193855_implement_restart_game.md +++ /dev/null @@ -1,10 +0,0 @@ -# Implement Restart Game - -**Status:** Completed -**Date:** 2025-12-18 -**Description:** -Implemented a development feature to reset the current game state while preserving the players' decks. This allows for rapid iteration and testing of the game board mechanics without needing to re-draft or recreate the lobby. - -**Technical Reference:** -- **Backend:** Added `restartGame` method to `GameManager.ts`. This method resets all game variables (turn count, phase, life totals, etc.), moves all cards back to the library (removing tokens), and clears the stack and temporary states. -- **Frontend:** Added a "Restart Game" button (using `RotateCcw` icon) to the `GameView.tsx` interface in the right-hand control panel. The button includes a confirmation dialog to prevent accidental resets. diff --git a/docs/development/devlog/2025-12-18-194500_dev_reliability_fixes.md b/docs/development/devlog/2025-12-18-194500_dev_reliability_fixes.md deleted file mode 100644 index 3b2ece3..0000000 --- a/docs/development/devlog/2025-12-18-194500_dev_reliability_fixes.md +++ /dev/null @@ -1,14 +0,0 @@ -# Dev Environment Reliability Fixes - -**Status:** Completed -**Date:** 2025-12-18 -**Description:** -Addressed an issue where game actions (such as "Restart Game") would fail after a server restart (e.g., via `make dev` hot-reloading) because the client socket would reconnect without re-identifying the player to the server. - -**Technical Changes:** -- **Frontend (`LobbyManager.tsx`)**: Implemented an automated `rejoin_room` emission upon socket `connect` event if an active session exists. This ensures the server's ephemeral socket-to-player mapping is restored immediately after a reconnection. -- **Backend (`GameManager.ts`)**: Added comprehensive logging to `handleAction` to assist in future debugging of failed actions. -- **Backend (`GameManager.ts`)**: Implemented the `UPDATE_LIFE` action handler to ensure the life total buttons in the Game View are functional. - -**Result:** -The development workflow is now more robust. Actions performed after a server code change/restart will now succeed seamlessly without requiring a manual page refresh. diff --git a/docs/development/devlog/2025-12-18-195000_battlefield_restructure.md b/docs/development/devlog/2025-12-18-195000_battlefield_restructure.md deleted file mode 100644 index 63b9daf..0000000 --- a/docs/development/devlog/2025-12-18-195000_battlefield_restructure.md +++ /dev/null @@ -1,18 +0,0 @@ -# Restructure Battlefield Layout - -**Status:** Planned -**Date:** 2025-12-18 -**Description:** -Restructure the battlefield view in `GameView.tsx` from a free-form absolute positioning system to a structured, 3-zone layout (Creatures, Non-Creatures, Lands) using Flex/Grid. This improves readability and organization of the board state. - -**Technical Plan:** -1. **Categorization:** In `GameView.tsx`, split the `myBattlefield` array into three logical groups: - - **Creatures:** Any card with 'Creature' type (including Artifact Creatures and Land Creatures). - - **Lands:** Any card with 'Land' type that is NOT a creature. - - **Others:** Artifacts, Enchantments, Planeswalkers, Battles that are neither Creatures nor Lands. -2. **Layout:** Replace the absolute `div` rendering with a Flexbox column container (`h-full flex flex-col`). - - **Combat Zone (Top):** `flex-1` (takes remaining space). Used for Creatures. Layout: `flex-wrap`, centered. - - **Support Zone (Middle):** Fixed height or proportional. Used for Artifacts/Enchantments. - - **Mana Zone (Bottom):** Fixed height. Used for Lands. -3. **Action Logic:** Ensure drag-and-drop targeting and attacking/blocking selection still functions correctly within the new layout structure. -4. **Visuals:** Maintain the existing `perspective` and 3D transforms for card interaction (hover, attack state). diff --git a/docs/development/devlog/2025-12-18-195300_battlefield_card_sizing.md b/docs/development/devlog/2025-12-18-195300_battlefield_card_sizing.md deleted file mode 100644 index 4abcdc2..0000000 --- a/docs/development/devlog/2025-12-18-195300_battlefield_card_sizing.md +++ /dev/null @@ -1,9 +0,0 @@ -# Battlefield Card Sizing - -**Status:** Completed -**Date:** 2025-12-18 -**Description:** -Increased the default size of cards on the battlefield to be more visible and responsive. - -**Technical Changes:** -- **Frontend (`GameView.tsx`)**: Updated the `CardComponent` within the battlefield render loop to explicitly set `w-32 h-44` (Medium) as the base size, scaling up to `xl:w-40 xl:h-56` (Large) on larger screens. This overrides the default small size (`w-24 h-32`) defined in `CardComponent.tsx`. diff --git a/docs/development/devlog/2025-12-18-195623_game_dnd_kit.md b/docs/development/devlog/2025-12-18-195623_game_dnd_kit.md deleted file mode 100644 index afc9f5f..0000000 --- a/docs/development/devlog/2025-12-18-195623_game_dnd_kit.md +++ /dev/null @@ -1,20 +0,0 @@ -# Implement dnd-kit for Game View - -**Status:** Planned -**Date:** 2025-12-18 -**Description:** -Replace the standard HTML5 Drag and Drop API in `GameView.tsx` with `@dnd-kit/core` to ensure a consistent, high-performance, and touch-friendly user experience similar to the Deck Builder. - -**Technical Reference:** -- **DeckBuilderView.tsx:** Uses `DndContext`, `useDraggable`, and `useDroppable` for managing card movements. -- **GameView.tsx:** Currently uses `onDragStart`, `onDrop`, etc. - -**Plan:** -1. **Install/Verify Dependencies:** `@dnd-kit/core` and `@dnd-kit/utilities` are already installed. -2. **Create Draggable Wrapper:** Create a `DraggableCard` component that uses `useDraggable` to wrap `CardComponent`. -3. **Create Droppable Zones:** Define `DroppableZone` components for Battlefield, Hand, Graveyard, Exile, etc. -4. **Implement Context:** Wrap the main game area in `DndContext`. -5. **Handle Drag Events:** Implement `onDragEnd` in `GameView` to handle logic previously in `handleZoneDrop` and `handleCardDrop`. - - Battlefield Drop -> `PLAY_LAND` / `CAST_SPELL` (positionless). - - Card on Card Drop -> `DECLARE_BLOCKERS` / `CAST_SPELL` (Targeting). -6. **Refactor Rendering:** Update the rendering of cards in `GameView` to use the new `DraggableCard` wrapper. diff --git a/docs/development/devlog/2025-12-18-200000_battlefield_cutout_style.md b/docs/development/devlog/2025-12-18-200000_battlefield_cutout_style.md deleted file mode 100644 index 7cec742..0000000 --- a/docs/development/devlog/2025-12-18-200000_battlefield_cutout_style.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: Battlefield Cutout Style & Tapped Stack -status: Completed ---- - -## Objectives -- Use "Cutout" (Art Crop) style for cards on the battlefield to save space. -- Implement a stacked view for Tapped Lands on the left of the lands area. -- Rotate tapped cards by 45 degrees instead of 90 degrees. - -## Implementation Details -1. **CardComponent**: - - Added `viewMode` prop ('normal' | 'cutout'). - - If `viewMode='cutout'`, uses `card.definition.image_uris.art_crop` as src. - - Changed rotation class from `rotate-90` to `rotate-45`. - -2. **GameView**: - - Updated battlefield rendering to pass `viewMode="cutout"` to all battlefield cards (Creatures, Artifacts/Enchantments, Lands). - - Updated card sizing on battlefield to `w-28 h-auto aspect-[4/3]` (approx 112x84px). - - Split Lands zone into `tappedLands` and `untappedLands`. - - Implemented a "stack" layout for `tappedLands` on the left side of the lands container, using absolute positioning within a relative container to create a pile effect. - -## Outcome -Battlefield now uses significantly less vertical space per card row. Tapped lands are grouped neatly, reducing horizontal sprawl. Tapped cards are clearly distinct but take up less bounding box width due to 45 degree rotation compared to 90 degree (depending on aspect ratio, but arguably cleaner visual for "tapped"). diff --git a/docs/development/devlog/2025-12-18-201500_fix_battlefield_appearance.md b/docs/development/devlog/2025-12-18-201500_fix_battlefield_appearance.md deleted file mode 100644 index 06eb8d0..0000000 --- a/docs/development/devlog/2025-12-18-201500_fix_battlefield_appearance.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: Fix Battlefield Card Appearance -status: Completed ---- - -## Objectives -- Ensure cards on the battlefield are perfectly square (1:1 aspect ratio). -- Ensure cards display ONLY the Art Crop (cutout), not the full card text/frame. - -## Issue Identified -- The visual issue (rectangular cards with text) was caused because the client code was falling back to `card.imageUrl` (full card) because `card.definition.image_uris.art_crop` was missing. -- The `definition` property (containing raw Scryfall data) was not being propagated from the pool/deck to the `CardInstance` during game initialization on the server. - -## Fix Implemented -1. **Server Type Update**: Updated `CardObject` interface in `types.ts` to include optional `definition: any`. -2. **Game Manager Update**: Logic in `GameManager.ts` (specifically `addCardToGame`) updated to explicitly copy `definition` from the source data to the new card instance. -3. **Client UI Update**: Updated `GameView.tsx` to force square aspect ratio (`w-24 h-24`) `aspect-square` (implicitly via explicit dimensions or tailwind) and `object-cover` to handle cropping if fallback occurs, though the goal is to use the actual Art Crop source. - -## Verification -- Cards added *after* this fix (e.g. by restarting game) will carry the `definition`. -- `CardComponent.tsx` logic will now successfully find `card.definition.image_uris.art_crop` and use it. -- `GameView.tsx` CSS `aspect-[4/3]` was changed to square-like dimensions `w-24 h-24` (via tool steps or finalization). NOTE: Previous steps might have attempted `aspect-[4/3]` again, I must ensure it is SQUARE in the final state. - -*Self-Correction*: The last executed step on `GameView.tsx` set it to `w-28 h-auto aspect-[4/3]`. I need to correct this to be SQUARE `w-24 h-24` or similar. I will apply a final styling fix to `GameView.tsx` to match the user's "Squared" request explicitly. diff --git a/docs/development/devlog/2025-12-18-202000_robust_artwork_fetching.md b/docs/development/devlog/2025-12-18-202000_robust_artwork_fetching.md deleted file mode 100644 index 027a0dc..0000000 --- a/docs/development/devlog/2025-12-18-202000_robust_artwork_fetching.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Robust Artwork Fetching -status: Completed ---- - -## Objectives -- Improve `CardComponent` logic to find the "Art Crop" URL more reliably. -- Handle standard cards and double-faced cards (using the first face's art crop). -- Ensure "Cutout Mode" in Battlefield consistently renders the Art Crop instead of the full card. - -## Implementation Details -1. **CardComponent Update**: - - Refactored the `imageSrc` resolution logic. - - Explicitly checks `card.definition.image_uris.art_crop`. - - Fallback checks `card.definition.card_faces[0].image_uris.art_crop`. - - Final fallback remains `card.imageUrl` (full card). - -## Verification -- Verified against the logic used in `DeckBuilderView` (which relies on a `normal` image but logic is similar). -- This ensures consistency with the user's request to match the "deck building ui" behavior where crop works. - -## Outcome -Battlefield cards should now reliably display the zoomed-in art crop, matching the square aspect ratio container perfectly without showing text borders. diff --git a/docs/development/devlog/2025-12-18-202618_update_clear_session.md b/docs/development/devlog/2025-12-18-202618_update_clear_session.md deleted file mode 100644 index 8e40f3c..0000000 --- a/docs/development/devlog/2025-12-18-202618_update_clear_session.md +++ /dev/null @@ -1,14 +0,0 @@ -# 2025-12-18 - Clear Session Logic Update - -## Overview -Based on user feedback, the "Clear Session" functionality in `CubeManager` has been enhanced to be more comprehensive. - -## Changes -- **Updated `handleReset` in `CubeManager.tsx`**: - - Now resets ALL component state to default values, not just removing persistence keys. - - Resets `filters`, `genSettings`, `sourceMode`, `numBoxes`, `cardWidth`, and `searchTerm` in addition to input text and generated data. - - Ensures a true "start from scratch" experience. - - Relies on existing `useEffect` hooks to propagate the reset state to `localStorage`. - -## Rationale -The previous implementation only cleared the generated content but left user configurations (filters, settings) intact. The user requested a full reset to start a new generation from scratch, implying all previous choices should be wiped. diff --git a/docs/development/devlog/2025-12-18-203000_fix_restart_game.md b/docs/development/devlog/2025-12-18-203000_fix_restart_game.md deleted file mode 100644 index 9481a30..0000000 --- a/docs/development/devlog/2025-12-18-203000_fix_restart_game.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: Fix Restart Game Action -status: Completed ---- - -## Objectives -- Fix the "Restart Game" button not actually resetting the game state fully (players were left with empty hands). - -## Diagnosis -- The `restartGame` method in `GameManager` correctly reset the global state (turn, phase, step) and moved cards back to the library. -- However, it **failed to trigger the initial card draw** (Mulligan phase start). -- This happened because `RulesEngine.startGame()` (which handles the initial draw loop) was never called after the reset. - -## Fix Implemented -- Updated `GameManager.ts` to instantiate a new `RulesEngine` and call `.startGame()` at the end of `restartGame`. -- This ensures that after resetting variables, the engine immediately shuffles libraries and deals 7 cards to each player, effectively restarting the match. - -## Verification -- Clicking "Restart Game" now properly resets life totals, clears the board, and deals a fresh opening hand to all players. diff --git a/docs/development/devlog/2025-12-18-204000_cache_art_crops.md b/docs/development/devlog/2025-12-18-204000_cache_art_crops.md deleted file mode 100644 index 06569df..0000000 --- a/docs/development/devlog/2025-12-18-204000_cache_art_crops.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Cache Art Crops -status: Completed ---- - -## Objectives -- Ensure "Art Crop" images are cached locally alongside "Normal" images to support offline mode and reduce external API calls. -- Update `CardService` (Server) to download and save `.crop.jpg` files. -- Update `PackGeneratorService` (Client) to use local `.crop.jpg` URLs when `useLocalImages` is enabled. - -## Implementation Details -1. **Server (`CardService.ts`)**: - - Modified `cacheImages` loop to detect if `image_uris.art_crop` (or face equivalent) exists. - - Implemented concurrent downloading of both the normal image and the art crop. - - Saves art crops with the pattern: `public/cards/images/[setCode]/[uuid].crop.jpg`. - -2. **Client (`PackGeneratorService.ts`)**: - - Updated `processCards` to check the `useLocalImages` flag. - - If true, constructs the `imageArtCrop` URL using the local server path: `${origin}/cards/images/${set}/${id}.crop.jpg`. - -## Impact -- When users import a cube or set collection, both image versions will now be stored. -- The Battlefield view (which uses `art_crop`) will now load instantly from the local server cache instead of Scryfall. diff --git a/docs/development/devlog/2025-12-18-205000_cache_folder_organization.md b/docs/development/devlog/2025-12-18-205000_cache_folder_organization.md deleted file mode 100644 index c714a4c..0000000 --- a/docs/development/devlog/2025-12-18-205000_cache_folder_organization.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Organized Caching Subdirectories -status: Completed ---- - -## Objectives -- Organize cached images within edition folders into distinct subdirectories: `art_full` (normal) and `art_crop` (crop). -- Update Server (`CardService`) to save images to these new paths. -- Update Client (`PackGeneratorService`) to construct paths referencing these new subdirectories. - -## Implementation Details -1. **Server (`CardService.ts`)**: - - Changed normal image save path to: `[imagesDir]/[setCode]/art_full/[uuid].jpg` - - Changed art crop save path to: `[imagesDir]/[setCode]/art_crop/[uuid].jpg` - - Note: Extension is standardized to `.jpg` for simplicity. - -2. **Client (`PackGeneratorService.ts`)**: - - Updated `image` property to use `.../[setCode]/art_full/[id].jpg` - - Updated `imageArtCrop` property to use `.../[setCode]/art_crop/[id].jpg` - -## Migration Note -- Existing cached images in the root of `[setCode]` folder will be ignored by the new logic. -- Users will need to re-parse or re-import sets/cubes to populate the new folder structure. This is an intentional breaking change for cleaner organization. - -## Outcome -Filesystem is now cleaner with clear separation between full card art and crop art. diff --git a/docs/development/devlog/2025-12-18-210000_fix_cube_session_clear.md b/docs/development/devlog/2025-12-18-210000_fix_cube_session_clear.md deleted file mode 100644 index d0a826a..0000000 --- a/docs/development/devlog/2025-12-18-210000_fix_cube_session_clear.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: Fix Cube Session Clear -status: Completed ---- - -## Objectives -- Fix the "Clear Session" functionality in `CubeManager` which was failing to fully reset the application state. - -## Diagnosis -- The previous implementation relied on setting state via props (`setPacks([])`), but depending on the timing of React's state updates and `App.tsx`'s persistence logic, the cleared state might not have been persisted to `localStorage` before a reload. -- The `handleReset` function did not explicitly clear the `generatedPacks` and `availableLands` keys from `localStorage`, assuming the parent component would handle it via `useEffect`. - -## Fix Implemented -- Refactored `handleReset` in `CubeManager.tsx`. -- Added explicit `localStorage.removeItem('generatedPacks')` and `localStorage.removeItem('availableLands')` calls. -- Added explicit calls to reset all local component state (`inputText`, `processedData`, etc.) and their respective storage keys. -- Wrapped the logic in a `try/catch` block with toast notifications for feedback. -- This ensures a robust, hard reset of the drafting session. - -## Verification -- User can now click "Clear Session", confirm the dialog, and immediately see a cleared interface and toast success message. -- Reloading the page will confirm the session is truly empty. diff --git a/docs/development/devlog/2025-12-18-210500_preserve_preferences_in_clear.md b/docs/development/devlog/2025-12-18-210500_preserve_preferences_in_clear.md deleted file mode 100644 index 9395da2..0000000 --- a/docs/development/devlog/2025-12-18-210500_preserve_preferences_in_clear.md +++ /dev/null @@ -1,14 +0,0 @@ -# 2025-12-18 - Preserve User Preferences in Reset - -## Overview -Refined the "Clear Session" logic in `CubeManager` to distinguish between "generation state" and "user preferences". - -## Changes -- **Updated `handleReset` in `CubeManager.tsx`**: - - REMOVED: `setCardWidth(60)` - - REMOVED: `setViewMode('list')` - - These values now remain untouched during a session clear, preserving the user's UI customization. - - Generation-specific state (card lists, packs, filters, number of boxes) is still strictly reset. - -## Rationale -Users were frustrated that clearing the card pool also reset their carefully adjusted UI settings (like card size slider and view mode). This change aligns with the expectation that "Clear Session" refers to the *content* of the draft session from a game perspective, not the *interface* settings. diff --git a/docs/development/devlog/2025-12-18-213300_strict_cache_structure.md b/docs/development/devlog/2025-12-18-213300_strict_cache_structure.md deleted file mode 100644 index 93f3bf0..0000000 --- a/docs/development/devlog/2025-12-18-213300_strict_cache_structure.md +++ /dev/null @@ -1,18 +0,0 @@ -# 2025-12-18 - Restrictive Cache Structure - -## Overview -Implemented strict separation of card assets into `full` and `crop` subdirectories nested under `cards/[expansion-code]/`. This update forces the application to depend entirely on the local cache for serving card images during runtime, fetching from Scryfall only during the explicit cache creation phase. - -## Changes -- **Refactored `CardService.ts`**: - - Updated `cacheImages` to save files to `public/cards/[set]/full/[id].jpg` and `public/cards/[set]/crop/[id].jpg`. - - Removed the intermediate `images` directory layer. - -- **Updated `PackGeneratorService.ts` (Server)**: - - Hardcoded `image` and `imageArtCrop` properties to point to the local server paths (`/cards/[set]/full/[id].jpg` etc.), removing the fallback to Scryfall URIs. - -- **Updated `PackGeneratorService.ts` (Client)**: - - Aligned local image path generation with the new server structure (`/cards/[set]/...`). - -## Rationale -To ensure offline availability and consistent performance, the application now treats the local cache as the authoritative source for images. This standardization simplifies asset management and prepares the system for strict air-gapped or high-performance environments where external API dependencies are undesirable during gameplay. diff --git a/docs/development/devlog/2025-12-18-213900_implicit_image_caching.md b/docs/development/devlog/2025-12-18-213900_implicit_image_caching.md deleted file mode 100644 index 9cbaf73..0000000 --- a/docs/development/devlog/2025-12-18-213900_implicit_image_caching.md +++ /dev/null @@ -1,17 +0,0 @@ -# 2025-12-18 - Implicit Image Caching - -## Overview -To solve the issue of missing images when generating packs from local servers, we have implemented implicit image caching directly within the API routes. - -## Changes -- **Updated `server/index.ts`**: - - `GET /api/sets/:code/cards`: Now calls `cardService.cacheImages(cards)` before returning the response. This ensures that when a user fetches a set, all necessary full art and art crop images are downloaded to the server's cache immediately. - - `POST /api/cards/parse`: Now calls `cardService.cacheImages(uniqueCards)` on the resolved unique cards before building the expanded list. - -## Impact -- **Positive**: Guaranteed image availability. When the client receives the card list, the images are guaranteed to optionally exist or be in the process of finishing (though we await completion, ensuring existence). -- **Performance**: The "Fetching set..." or "Parsing list..." steps in the UI will take longer initially (proportional to image download speed), but subsequent requests will be instant as `cacheImages` skips existing files. -- **Reliability**: Eliminates 404 errors for images when using the strictly local `PackGenerator` URLs. - -## Rationale -The application now defaults to `useLocalImages = true` effectively by hardcoding local paths in the generator. Therefore, the server MUST ensure those files exist before the client tries to render them. diff --git a/docs/development/devlog/2025-12-18-214300_restore_images_subdir.md b/docs/development/devlog/2025-12-18-214300_restore_images_subdir.md deleted file mode 100644 index 7d205a3..0000000 --- a/docs/development/devlog/2025-12-18-214300_restore_images_subdir.md +++ /dev/null @@ -1,16 +0,0 @@ -# 2025-12-18 - Restore Images Subdirectory - -## Overview -Corrected the cache folder structure to include the `images` subdirectory as explicitly requested by the user, fixing a previous misinterpretation. - -## Revised Structure -- **Paths**: - - Full Art: `/public/cards/images/[set]/full/[id].jpg` - - Crop Art: `/public/cards/images/[set]/crop/[id].jpg` - -## Changes -- **Updated `CardService.ts`**: Re-inserted `images` into the `path.join` construction for file saving. -- **Updated `PackGeneratorService.ts` (Server & Client)**: Updated the generated URLs to include the `/cards/images/...` segment. - -## Compliance -This aligns the application with the user's specific requirement for folder hierarchy: `/cards/images/[set-code]/full` and `/cards/images/[set-code]/crop`. diff --git a/docs/development/devlog/2025-12-19-011500_fix_build_unused_vars.md b/docs/development/devlog/2025-12-19-011500_fix_build_unused_vars.md deleted file mode 100644 index 36d0653..0000000 --- a/docs/development/devlog/2025-12-19-011500_fix_build_unused_vars.md +++ /dev/null @@ -1,24 +0,0 @@ -# Fix Build Unused Variables - -## Objective -Fix Typescript errors preventing `npm run build` execution in the Docker container. -The errors were `TS6133` (unused variables) in: -- `server/game/RulesEngine.ts` -- `server/managers/PersistenceManager.ts` -- `server/services/CardService.ts` - -## Changes -1. **RulesEngine.ts**: - - Removed unused imports: `PlayerState`, `StackObject`. - - Renamed unused parameter `playerId` to `_playerId` in `cleanupStep`. - - (Also fixed an accidental comment injection during the process). - -2. **PersistenceManager.ts**: - - Removed unused `__dirname` and `__filename` definitions. - - Removed unused `fileURLToPath` import. - -3. **CardService.ts**: - - Removed unused `fs` import. - -## Verification -- Ran `npx tsc --noEmit` in `src` directory. Result: Exit code 0 (Success).