February 2026 Improvements: Bidirectional Trains, Koin Testing, and Code Quality#358
February 2026 Improvements: Bidirectional Trains, Koin Testing, and Code Quality#358bedaHovorka merged 18 commits intodevelopfrom
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
|
@bedaHovorka I've opened a new pull request, #359, to work on those changes. Once the pull request is ready, I'll request review from you. |
|
@bedaHovorka I've opened a new pull request, #360, to work on those changes. Once the pull request is ready, I'll request review from you. |
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
bedaHovorka
left a comment
There was a problem hiding this comment.
@copilot cherry-pick last commit from develop
This comment was marked as resolved.
This comment was marked as resolved.
de72648 to
5a741a4
Compare
|
@copilot open a new pull request to apply changes based on the comments in this thread |
|
@bedaHovorka I've opened a new pull request, #361, to work on those changes. Once the pull request is ready, I'll request review from you. |
This comment was marked as outdated.
This comment was marked as outdated.
…clear operations (#338) Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com>
* Add PropertyChangeEvent firing to BaseContext property setters - Add custom setters to currentMaxSpeed, currentTrackLength, currentNameString - Fire PropertyChangeEvent when property values change - Add comprehensive unit tests for property change events - Update integration tests to verify event firing - Resolves issue with GUI components not being notified of property changes Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com> * Fix currentNameString property change event to use getter for old value The currentNameString setter was using the nullable backing field (nameString) for the old value in PropertyChangeEvent, but the getter returns empty string when null. This caused inconsistency between the property's apparent old value and the event's old value. Now using the getter to get a consistent old value. Also updated the test to assert on the old value. * Fix currentNameString setter to avoid polymorphic getter call The setter was calling currentNameString getter to get the old value, but this causes issues with DefaultSimulationContext which overrides the getter with random generation logic. When super.currentNameString is set from the subclass, the BaseContext setter would call the overridden getter, potentially getting a random value instead of the actual old value. Fixed by using backing field directly with same null-handling logic as getter: nameString ?: "" This avoids virtual method calls during property assignment and ensures the old value in PropertyChangeEvent is correct even when called from subclasses. --------- Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com>
…r strategy (#336) * Initial plan * Implement eager track wrapping for Issue #214 - Update toDynamic(TrackFacility) to throw exception instead of lazy creation - All tracks already wrapped eagerly in initializeDynamicMapping() (lines 736-763) - Add EagerTrackWrappingTest with comprehensive test coverage - Update TrackDynamicMappingTest to reflect eager wrapping behavior - Consistent with path separator wrapping strategy Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com> * Add comprehensive documentation for Issue #214 - Created ISSUE_214_IMPLEMENTATION_SUMMARY.md with complete analysis - Documents problem statement, solution, and benefits - Lists all file changes and test coverage - Includes validation status and backward compatibility analysis Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com> * Add visual explanation for Issue #214 - Created ISSUE_214_VISUAL_EXPLANATION.md with diagrams - Shows before/after architecture comparison - Includes timeline comparison and code examples - Explains initialization flow and simulation impact Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com> * Fix CI build errors in test files (Issue #214) - Replace SimpleTrackBlock.getInstance() with proper constructor - Add RailSemaphore imports and create proper test track objects - Fix type inference in assertThat lambda by adding explicit Unit return - Both issues identified in code review comment #3760719655 Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com> * Fix assertThat usage in test files - use assertFailure instead - Replace assertThat{}.isFailure() with assertFailure{} pattern - Remove isFailure() import, add assertFailure import - Fixes Kotlin compilation error in EagerTrackWrappingTest.kt line 64 - Also fix TrackDynamicMappingTest.kt for consistency - Addresses code review comment #3761156459 Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com> * Fix assertFailure message assertion - use message().contains() pattern - Replace messageContains() with message().isNotNull().contains() - Remove messageContains import, add contains import - Fixes receiver type mismatch error in EagerTrackWrappingTest.kt line 69 - Uses correct assertk API pattern matching other tests (InOutValidationTest, TracksPolishTest) - Addresses code review comment #3761547032 Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com> * Fix assertk message assertion - use transform pattern instead of message() - Replace .message().isNotNull() with .transform { it.message ?: "" } - This is the correct assertk API for accessing exception messages - Matches pattern used in InOutValidationTest - Fixes compilation error: Unresolved reference 'message' - Addresses code review comment #3762776391 Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com> * Fix contains assertion - cast strings to CharSequence - Cast string literals to CharSequence in contains() calls - This resolves Kotlin compilation error with Assert<String>.contains() - Matches pattern used in TracksPolishTest for string assertions - Fixes compilation error in compileTestKotlin step - Addresses code review comment #3762987304 Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com> * Fix chained contains calls - use varargs instead - Replace chained .contains() calls with single varargs contains() - Pass multiple CharSequence values to single contains() call - This is the correct assertk API for checking multiple substrings - Matches pattern used in TracksPolishTest - Fixes compilation error at line 70 - Addresses code review comment #3763344015 Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com> * Fix PathTrackIntegrationTest - initialize dynamic mappings in setUp - Add initializeDynamicMapping() calls in test setUp for both contexts - Required because tests use toDynamic() without calling run() - Issue #214: Tracks now wrapped eagerly, lazy fallback removed - Fixes IllegalStateException: "Map contains 0 entries" - Addresses code review comment #3763464348 Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com>
…ry path unavailability (#352) * Update test files to use PathResult sealed class instead of nullable Path - Added PathResult import to all affected test files - Changed assertions from isNotNull() to isInstanceOf(PathResult.Available::class) - Extract path from Available result using: val path = (result as PathResult.Available).path - Changed null assertions to appropriate PathResult variants: - PathResult.OwnershipConflict: when blocks owned by different train or no reservation - PathResult.NoTopologicalPath: when network topology doesn't support path - Updated test comments and descriptions to mention PathResult variants Files updated: - TrainNavigationServiceTest.kt (14 Available, 9 OwnershipConflict, 4 NoTopologicalPath) - TrainPathReservationIntegrationTest.kt (5 Available, 7 OwnershipConflict) - PathDynamicReferencesTest.kt (2 Available) - NavigationModuleKoinTest.kt (2 Available, 1 OwnershipConflict) Total: 23 Available, 17 OwnershipConflict, 4 NoTopologicalPath instances * Implement PathResult sealed class to distinguish permanent vs temporary path unavailability * Fix type mismatch: extract Path from PathResult.Available before passing to extractNavigationBlocks * Fix remaining 3 test assertions: change isNotNull to isInstanceOf(PathResult.Available) --------- Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com>
…ng (#361) * Address PR review comments: fix indentation, resource leak, test naming, and documentation --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com>
…ments This commit addresses all 5 issues (2 Critical, 3 Major) identified in PR #358 code review: **Critical Issues:** 1. Train.kt PathResult Logic - Added explicit justification comments at 3 locations explaining why sim/ package modifications comply with conservative approach: - Type safety benefits of PathResult sealed class - Zero performance overhead (no boxing) - Physics validation references (TRAIN_PASSIVATION_FIX.md) - Comprehensive test coverage 2. hold(5.0) Polling - Added performance trade-off documentation: - Polling overhead: 0.2 wakeups/second per blocked train (acceptable) - Why passivate() was rejected (motor creeping bug) - Physics validation metrics (velocity: 8.48E-4 → 0.0 m/s) **Major Issues:** 3. MIN_INOUT_ELEMENTS Documentation - Fixed hardcoded "2" in error message: - Changed to use MIN_INOUT_ELEMENTS constant - Added note about bidirectional train operation (Issue #356) - Added regression test to verify error message accuracy 4. Lenient XML Validation - Added pre-save validation: - XMLContextFactory.saveContext() validates InOut count before serialization - MenuBar shows warning when opening invalid contexts - MenuBar shows specific error when save fails due to validation - Added 3 new tests for save rejection behavior 5. HashMapGraph Thread-Safety - Added comprehensive documentation: - Class-level KDoc explaining non-thread-safe design decision - Method-level KDoc for nodeSet() cache implementation - Usage guidelines and references to BaseContext/ContextConcurrencyTest **Testing:** - All 1912 tests passing (1 skipped, 0 failed) - 4 new tests added (1 for error message, 3 for save validation) - Code quality checks passing (detekt, ktlintCheck) **Impact:** - No breaking changes to public API - Conservative approach maintained (minimal logic changes to sim/) - Documentation-heavy changes with comprehensive validation Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
7ed71a1 to
0db384f
Compare
Code Review - PR #358Executive SummaryThis PR represents a high-quality architectural enhancement. Overall Assessment: APPROVED WITH MINOR COMMENTS Key Strengths
Issues FoundMajor (1 issue)Engineer Delay Calculation Inconsistency (Train.kt:906-908) - Comment says 200m at 1.5 m/s but uses 30 second delay. Math shows 200m / 1.5 m/s = 133 seconds not 30. Recommendation: Fix comment to match actual delay rationale. Medium (2 issues)
Minor (3 issues)
Performance AnalysisAll performance decisions validated:
Test CoverageStatistics: 1840 tests (1836 passing, 4 skipped), 51% code coverage Coverage Gaps:
CLAUDE.md ComplianceAll guidelines met: Minimal sim/ changes, no refactoring, tests required, quality gates passing Final VerdictAPPROVED - Risk Level: LOW, Breaking Changes: NONE, Backward Compatibility: FULL Recommendation: Merge after addressing engineer delay comment. Other issues are minor enhancements. Review by Claude Sonnet 4.5 following CLAUDE.md standards |
|
- Rename editingContextFactory to xmlContextFactory in OpenAction to avoid confusion with EditingContextFactory (reviewer comment MenuBar.kt:73) - Fix placeholder comment Issue #XXX PR #358 to Issue #80 (MenuBar.kt:103) - Rename inOutCount to inOutsCount for consistency (MenuBar.kt:202) - Rename docs/issues/issue-80.md to issue_80.md to match underscore convention - Update issue_80.md dialog text excerpt to match current implementation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace placeholder references "Issue #XXX, PR #358" with correct "Issue #80, PR #357" in XMLContextFactory.kt (both saveContext KDocs) and XMLContextFactoryOutputStreamTest.kt (@DisplayName annotation) - Delete docs/issues/issue-80.md stub (redirect to issue_80.md); README.md already links to the canonical issue_80.md file Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rename editingContextFactory to xmlContextFactory in OpenAction to avoid confusion with EditingContextFactory (reviewer comment MenuBar.kt:73) - Fix placeholder comment Issue #XXX PR #358 to Issue #80 (MenuBar.kt:103) - Rename inOutCount to inOutsCount for consistency (MenuBar.kt:202) - Rename docs/issues/issue-80.md to issue_80.md to match underscore convention - Update issue_80.md dialog text excerpt to match current implementation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace placeholder references "Issue #XXX, PR #358" with correct "Issue #80, PR #357" in XMLContextFactory.kt (both saveContext KDocs) and XMLContextFactoryOutputStreamTest.kt (@DisplayName annotation) - Delete docs/issues/issue-80.md stub (redirect to issue_80.md); README.md already links to the canonical issue_80.md file Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rename editingContextFactory to xmlContextFactory in OpenAction to avoid confusion with EditingContextFactory (reviewer comment MenuBar.kt:73) - Fix placeholder comment Issue #XXX PR #358 to Issue #80 (MenuBar.kt:103) - Rename inOutCount to inOutsCount for consistency (MenuBar.kt:202) - Rename docs/issues/issue-80.md to issue_80.md to match underscore convention - Update issue_80.md dialog text excerpt to match current implementation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace placeholder references "Issue #XXX, PR #358" with correct "Issue #80, PR #357" in XMLContextFactory.kt (both saveContext KDocs) and XMLContextFactoryOutputStreamTest.kt (@DisplayName annotation) - Delete docs/issues/issue-80.md stub (redirect to issue_80.md); README.md already links to the canonical issue_80.md file Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rename editingContextFactory to xmlContextFactory in OpenAction to avoid confusion with EditingContextFactory (reviewer comment MenuBar.kt:73) - Fix placeholder comment Issue #XXX PR #358 to Issue #80 (MenuBar.kt:103) - Rename inOutCount to inOutsCount for consistency (MenuBar.kt:202) - Rename docs/issues/issue-80.md to issue_80.md to match underscore convention - Update issue_80.md dialog text excerpt to match current implementation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace placeholder references "Issue #XXX, PR #358" with correct "Issue #80, PR #357" in XMLContextFactory.kt (both saveContext KDocs) and XMLContextFactoryOutputStreamTest.kt (@DisplayName annotation) - Delete docs/issues/issue-80.md stub (redirect to issue_80.md); README.md already links to the canonical issue_80.md file Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rename editingContextFactory to xmlContextFactory in OpenAction to avoid confusion with EditingContextFactory (reviewer comment MenuBar.kt:73) - Fix placeholder comment Issue #XXX PR #358 to Issue #80 (MenuBar.kt:103) - Rename inOutCount to inOutsCount for consistency (MenuBar.kt:202) - Rename docs/issues/issue-80.md to issue_80.md to match underscore convention - Update issue_80.md dialog text excerpt to match current implementation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace placeholder references "Issue #XXX, PR #358" with correct "Issue #80, PR #357" in XMLContextFactory.kt (both saveContext KDocs) and XMLContextFactoryOutputStreamTest.kt (@DisplayName annotation) - Delete docs/issues/issue-80.md stub (redirect to issue_80.md); README.md already links to the canonical issue_80.md file Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rename editingContextFactory to xmlContextFactory in OpenAction to avoid confusion with EditingContextFactory (reviewer comment MenuBar.kt:73) - Fix placeholder comment Issue #XXX PR #358 to Issue #80 (MenuBar.kt:103) - Rename inOutCount to inOutsCount for consistency (MenuBar.kt:202) - Rename docs/issues/issue-80.md to issue_80.md to match underscore convention - Update issue_80.md dialog text excerpt to match current implementation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace placeholder references "Issue #XXX, PR #358" with correct "Issue #80, PR #357" in XMLContextFactory.kt (both saveContext KDocs) and XMLContextFactoryOutputStreamTest.kt (@DisplayName annotation) - Delete docs/issues/issue-80.md stub (redirect to issue_80.md); README.md already links to the canonical issue_80.md file Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rename editingContextFactory to xmlContextFactory in OpenAction to avoid confusion with EditingContextFactory (reviewer comment MenuBar.kt:73) - Fix placeholder comment Issue #XXX PR #358 to Issue #80 (MenuBar.kt:103) - Rename inOutCount to inOutsCount for consistency (MenuBar.kt:202) - Rename docs/issues/issue-80.md to issue_80.md to match underscore convention - Update issue_80.md dialog text excerpt to match current implementation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace placeholder references "Issue #XXX, PR #358" with correct "Issue #80, PR #357" in XMLContextFactory.kt (both saveContext KDocs) and XMLContextFactoryOutputStreamTest.kt (@DisplayName annotation) - Delete docs/issues/issue-80.md stub (redirect to issue_80.md); README.md already links to the canonical issue_80.md file Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rename editingContextFactory to xmlContextFactory in OpenAction to avoid confusion with EditingContextFactory (reviewer comment MenuBar.kt:73) - Fix placeholder comment Issue #XXX PR #358 to Issue #80 (MenuBar.kt:103) - Rename inOutCount to inOutsCount for consistency (MenuBar.kt:202) - Rename docs/issues/issue-80.md to issue_80.md to match underscore convention - Update issue_80.md dialog text excerpt to match current implementation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace placeholder references "Issue #XXX, PR #358" with correct "Issue #80, PR #357" in XMLContextFactory.kt (both saveContext KDocs) and XMLContextFactoryOutputStreamTest.kt (@DisplayName annotation) - Delete docs/issues/issue-80.md stub (redirect to issue_80.md); README.md already links to the canonical issue_80.md file Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rename editingContextFactory to xmlContextFactory in OpenAction to avoid confusion with EditingContextFactory (reviewer comment MenuBar.kt:73) - Fix placeholder comment Issue #XXX PR #358 to Issue #80 (MenuBar.kt:103) - Rename inOutCount to inOutsCount for consistency (MenuBar.kt:202) - Rename docs/issues/issue-80.md to issue_80.md to match underscore convention - Update issue_80.md dialog text excerpt to match current implementation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace placeholder references "Issue #XXX, PR #358" with correct "Issue #80, PR #357" in XMLContextFactory.kt (both saveContext KDocs) and XMLContextFactoryOutputStreamTest.kt (@DisplayName annotation) - Delete docs/issues/issue-80.md stub (redirect to issue_80.md); README.md already links to the canonical issue_80.md file Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>




February 2026 Improvements: Bidirectional Trains, Koin Testing, and Code Quality
📊 PR Summary
test_cleanup🚀 Key Features
1. Bidirectional Train Operation
Full support for bidirectional train movement, enabling single-InOut networks.
Includes: #356, #359, #261
2. Context System Improvements
Enhanced context architecture with better validation and observability.
Includes: #353, #339, #352
3. Koin DI & Performance Testing
Comprehensive scope lifecycle tests and JMH performance benchmarks.
Includes: #346, #345, #343
✅ Code Quality & API Improvements
API Enhancements
Includes: #342, #350
Code Quality
Includes: #360, #361
Data Structures & Internal Improvements
Includes: #338, #337, #336, #340
🐛 Bug Fixes
📋 Complete Issue List
This PR includes the following 17 already-merged issues:
#261, #336, #337, #338, #339, #340, #342, #343, #345, #346, #350, #352, #353, #356, #359, #360, #361
✨ Key Achievements
📝 Review Notes
Ready for merge ✅