Skip to content

Improve game data handling#262

Open
ThadHouse wants to merge 3 commits intoTeam254:mainfrom
ThadHouse:improvedgamedata
Open

Improve game data handling#262
ThadHouse wants to merge 3 commits intoTeam254:mainfrom
ThadHouse:improvedgamedata

Conversation

@ThadHouse
Copy link
Contributor

@ThadHouse ThadHouse commented Feb 27, 2026

The existing game data method had a few flaws. It would only send to DS's that were connected when the send was triggered. This means that if a DS was disconnected when triggered, or if a DS disconnected after triggering, a DS might not get game data updates.

Solve this by checking if there is new game data to send during the dsConn update, and if so triggering the send.

This will also make the new game data method in 2027 easier, as that is likely transitioning to sending game data over the UDP packet instead of over TCP.

Summary by CodeRabbit

  • New Features
    • Per-station game data management with per-station delivery to driver stations
    • Game data automatically resets at match initialization
    • Real-time detection and propagation of game data changes to connected driver stations

@coderabbitai
Copy link

coderabbitai bot commented Feb 27, 2026

Warning

Rate limit exceeded

@ThadHouse has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 4 minutes and 26 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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.

📥 Commits

Reviewing files that changed from the base of the PR and between 93942eb and 9b1ecc5.

📒 Files selected for processing (1)
  • field/driver_station_connection.go
📝 Walkthrough

Walkthrough

This change adds per-station GameData to AllianceStation, resets it at match start (PreMatch), and propagates station-specific GameData through updated DriverStationConnection methods with a change-detection helper that sends game-data packets when needed.

Changes

Cohort / File(s) Summary
Per-Station Game Data Storage
field/arena.go
Added GameData string to AllianceStation. Initialize GameData to empty string at PreMatch start and pass station-specific GameData when updating driver-station connections.
Game Data Propagation & Change Detection
field/driver_station_connection.go
Added SentGameData string. Updated update(arena)update(arena, gameData) and sendControlPacket(arena)sendControlPacket(arena, gameData). Introduced checkGameData(gameData) to detect changes, call sendGameDataPacket(), and update SentGameData.
Test Updates
field/driver_station_connection_test.go
Adjusted test call sites to pass the additional gameData string to sendControlPacket, matching the new signature.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Arena
participant DSConn as DriverStationConnection
participant DS as DriverStation
Arena->>Arena: PreMatch — set AllianceStation.GameData = ""
Arena->>DSConn: update(arena, allianceStation.GameData)
DSConn->>DSConn: checkGameData(gameData)
alt GameData changed
DSConn->>DS: sendGameDataPacket(gameData)
DS-->>DSConn: ack / success
DSConn->>DSConn: SentGameData = gameData
else No change
DSConn-->>DS: no game-data packet sent
end
DSConn->>DS: sendControlPacket(arena, gameData)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hop and note each byte and flag,

GameData tucked in every flagging bag,
When matches start I clear the slate,
Watch packets leap to update,
Happy hops — the arena's not drab!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Improve game data handling' clearly and concisely summarizes the main objective of the changeset, which focuses on enhancing game data transmission to driver stations by checking for updates during dsConn updates.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
field/driver_station_connection_test.go (1)

210-211: ⚠️ Potential issue | 🟡 Minor

Fix race condition: test waits too briefly for connection setup to complete.

The test sends a driver station connection packet (line 203), sleeps for only 10ms (line 209), then immediately asserts DsConn is non-nil (line 211). However, listenForDriverStations() runs asynchronously in a separate goroutine, and the DsConn assignment at driver_station_connection.go:384 is not guaranteed to complete within 10ms. The delay should be increased, or the test should wait until the connection is established before proceeding.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@field/driver_station_connection_test.go` around lines 210 - 211, The test
currently sleeps 10ms then asserts arena.AllianceStations["B2"].DsConn is
non-nil, which races with the asynchronous listenForDriverStations goroutine;
replace the fixed short sleep with a deterministic wait loop or synchronization
so the test blocks until DsConn is set (e.g., poll
arena.AllianceStations["B2"].DsConn for non-nil with a reasonable timeout like
1s, or use a channel/WaitGroup signaled by the connection setup in
listenForDriverStations) before calling assert.NotNil on dsConn.
🧹 Nitpick comments (2)
field/arena.go (1)

643-646: Consider initializing GameData only on state transition.

This code runs on every Update() call while in PreMatch state (every 10ms), repeatedly setting GameData to empty. While functionally correct, it would be more efficient to only clear GameData once when transitioning into PreMatch or when the match is loaded.

♻️ Suggested optimization
 case PreMatch:
 	auto = true
 	enabled = false
-	// Set all game data values to empty
-	for _, allianceStation := range arena.AllianceStations {
-		allianceStation.GameData = ""
-	}

And add the initialization in LoadMatch() or ResetMatch() where it would only execute once:

// In LoadMatch() after resetting scores
for _, allianceStation := range arena.AllianceStations {
    allianceStation.GameData = ""
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@field/arena.go` around lines 643 - 646, The loop that clears
allianceStation.GameData inside Update() while in the PreMatch state should be
moved so it runs only once on state transition; remove the per-tick loop that
sets arena.AllianceStations[*].GameData = "" from Update()/PreMatch and instead
initialize/clear GameData for each entry in arena.AllianceStations within
LoadMatch() (or ResetMatch()) right after match loading/reset logic so GameData
is set once when the match is loaded or the state transitions into PreMatch.
field/driver_station_connection.go (1)

449-458: SentGameData is updated before sending, preventing retries on failure.

If sendGameDataPacket fails (line 453-456), SentGameData has already been updated (line 451), so subsequent calls won't attempt to resend the data. Consider updating SentGameData only after a successful send if retry behavior is desired.

♻️ Proposed fix for retry-safe error handling
 func (dsConn *DriverStationConnection) checkGameData(gameData string) {
 	needsGameDataUpdate := dsConn.SentGameData != gameData
-	dsConn.SentGameData = gameData
 	if needsGameDataUpdate {
 		err := dsConn.sendGameDataPacket(gameData)
 		if err != nil {
 			log.Printf("Error sending game data packet to Team %d: %v", dsConn.TeamId, err)
+		} else {
+			dsConn.SentGameData = gameData
 		}
 	}
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@field/driver_station_connection.go` around lines 449 - 458, The checkGameData
method updates dsConn.SentGameData before attempting to send, preventing retries
if sendGameDataPacket fails; modify checkGameData so it only sets
dsConn.SentGameData = gameData after sendGameDataPacket returns nil, i.e., call
sendGameDataPacket(gameData) when needsGameDataUpdate is true and on success
assign SentGameData, logging the error (using dsConn.TeamId) on failure without
mutating SentGameData so subsequent calls will retry.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@field/driver_station_connection_test.go`:
- Around line 210-211: The test currently sleeps 10ms then asserts
arena.AllianceStations["B2"].DsConn is non-nil, which races with the
asynchronous listenForDriverStations goroutine; replace the fixed short sleep
with a deterministic wait loop or synchronization so the test blocks until
DsConn is set (e.g., poll arena.AllianceStations["B2"].DsConn for non-nil with a
reasonable timeout like 1s, or use a channel/WaitGroup signaled by the
connection setup in listenForDriverStations) before calling assert.NotNil on
dsConn.

---

Nitpick comments:
In `@field/arena.go`:
- Around line 643-646: The loop that clears allianceStation.GameData inside
Update() while in the PreMatch state should be moved so it runs only once on
state transition; remove the per-tick loop that sets
arena.AllianceStations[*].GameData = "" from Update()/PreMatch and instead
initialize/clear GameData for each entry in arena.AllianceStations within
LoadMatch() (or ResetMatch()) right after match loading/reset logic so GameData
is set once when the match is loaded or the state transitions into PreMatch.

In `@field/driver_station_connection.go`:
- Around line 449-458: The checkGameData method updates dsConn.SentGameData
before attempting to send, preventing retries if sendGameDataPacket fails;
modify checkGameData so it only sets dsConn.SentGameData = gameData after
sendGameDataPacket returns nil, i.e., call sendGameDataPacket(gameData) when
needsGameDataUpdate is true and on success assign SentGameData, logging the
error (using dsConn.TeamId) on failure without mutating SentGameData so
subsequent calls will retry.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bc660ae and 7edb24b.

📒 Files selected for processing (3)
  • field/arena.go
  • field/driver_station_connection.go
  • field/driver_station_connection_test.go

@ThadHouse
Copy link
Contributor Author

I have no clue why that test is failing. It's passing locally.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@field/driver_station_connection.go`:
- Around line 449-459: checkGameData currently swallows send errors from
sendGameDataPacket causing update() to appear successful; change checkGameData
to return an error (instead of void), call sendGameDataPacket and if it returns
an error return that error (do NOT set dsConn.SentGameData on failure), and
update callers (e.g., update()) to propagate or handle the returned error so TCP
send failures are surfaced rather than only logged; ensure references to
dsConn.SentGameData and sendGameDataPacket are preserved and error paths
log/contextualize before propagating.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7edb24b and 93942eb.

📒 Files selected for processing (1)
  • field/driver_station_connection.go

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant