Refactor Stall Interaction and Optimize Placement Validation - #168
Conversation
- Extracted special mode and stall build/selection logic from onCellClick into specialized handler methods. - Optimized validateStallPlacement to avoid redundant A* pathfinding for enemies whose paths are not intersected by new stalls. - Improved atomicity of sellStall and undoSell by moving hex map and validation logic into _gameState.update blocks. - Streamlined Tray Return Uncle rule check using idiomatic Kotlin. - Updated fixes.md with REF-013 and marked REF-012 as Resolved. Co-authored-by: candour <4670475+candour@users.noreply.github.com>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthrough
ChangesStall Placement Validation and Interaction Refactoring
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Build Successful! 🚀Note: This link will be removed when the PR is closed. |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
app/src/main/java/com/messark/hawker/MainViewModel.kt (1)
1111-1134: 💤 Low valueConsider moving validation inside
_gameState.updatefor consistency.
handleBuildStallperforms gold validation andvalidateStallPlacementchecks againstcurrentStatecaptured outside the update block, then applies modifications usingstateinside. This creates a potential TOCTOU window and is inconsistent with the atomic pattern applied tosellStallandundoSell.On single-threaded Compose UI this is unlikely to cause issues, but aligning all stall operations to the same atomic pattern would improve consistency.
♻️ Suggested refactor to match sellStall/undoSell pattern
private fun handleBuildStall(coord: AxialCoordinate, tile: HexTile, currentState: GameState) { - val stallToPlace = currentState.selectedStallType ?: return - if (currentState.gold >= stallToPlace.cost && (tile.type == TileType.FLOOR || tile.type == TileType.DRAIN)) { - val blocked = validateStallPlacement(coord, stallToPlace, currentState) - - if (blocked != null) { - val newHexes = currentState.hexes.toMutableMap() - newHexes[coord] = tile.copy( - stall = stallToPlace.copy(id = UUID.randomUUID().toString()), - isPermanentlyWet = false - ) - - _gameState.update { state -> - val updatedEnemies = recalculateEnemyPaths(state, blocked, newHexes) - state.copy( - hexes = newHexes, - gold = state.gold - stallToPlace.cost, - enemies = updatedEnemies, - lastSoldStall = null - ) - } - } - } + _gameState.update { state -> + val stallToPlace = state.selectedStallType ?: return@update state + val currentTile = state.hexes[coord] ?: return@update state + if (state.gold < stallToPlace.cost) return@update state + if (currentTile.type != TileType.FLOOR && currentTile.type != TileType.DRAIN) return@update state + + val blocked = validateStallPlacement(coord, stallToPlace, state) ?: return@update state + + val newHexes = state.hexes.toMutableMap() + newHexes[coord] = currentTile.copy( + stall = stallToPlace.copy(id = UUID.randomUUID().toString()), + isPermanentlyWet = false + ) + + val updatedEnemies = recalculateEnemyPaths(state, blocked, newHexes) + state.copy( + hexes = newHexes, + gold = state.gold - stallToPlace.cost, + enemies = updatedEnemies, + lastSoldStall = null + ) + } }
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 34b45b13-ac30-47b7-8c2b-05b9a391cc30
📒 Files selected for processing (2)
app/src/main/java/com/messark/hawker/MainViewModel.ktfixes.md
|
Date appears to be incorrect. |
|
Consider moving validation inside _gameState.update for consistency. handleBuildStall performs gold validation and validateStallPlacement checks against currentState captured outside the update block, then applies modifications using state inside. This creates a potential TOCTOU window and is inconsistent with the atomic pattern applied to sellStall and undoSell. On single-threaded Compose UI this is unlikely to cause issues, but aligning all stall operations to the same atomic pattern would improve consistency. |
Good point! I've refactored |
- Extracted special mode and stall build/selection logic from onCellClick into specialized handler methods. - Optimized validateStallPlacement to avoid redundant A* pathfinding for enemies whose paths are not intersected by new stalls. - Improved atomicity of handleBuildStall, sellStall and undoSell by moving all validation and hex map updates inside _gameState.update blocks. - Streamlined Tray Return Uncle rule check using idiomatic Kotlin. - Updated fixes.md with REF-013 and marked REF-012 as Resolved. Co-authored-by: candour <4670475+candour@users.noreply.github.com>
Build Successful! 🚀Note: This link will be removed when the PR is closed. |
I have refactored the stall interaction logic in
MainViewModel.ktto improve modularity and performance. Specifically:onCellClickhas been simplified into a router that delegates to specialized methods likehandleBuildStall,handleStallSelection, and mode-specific handlers for pillar removal and outdoor puddles.validateStallPlacementnow skips expensive A* pathfinding for any enemy whose current path doesn't actually pass through the coordinate of the new stall. This significantly reduces the computational overhead during stall placement.sellStallandundoSellnow perform their validation and state modifications entirely within the_gameState.updateblock, ensuring atomic state transitions and better thread safety.anyandnonefor better readability.I have also updated
fixes.mdto reflect these improvements and marked the previous engine optimization (REF-012) as resolved. All relevant unit tests passed successfully.PR created automatically by Jules for task 11767897202155615896 started by @candour
Summary by CodeRabbit
Refactor
Chores