feat(#674): Add eccentric load option for Old School mode#683
feat(#674): Add eccentric load option for Old School mode#6839thLevelSoftware wants to merge 56 commits into
Conversation
Reuse the Echo 0x4E BLE packet for Old School exercises with eccentric load > 100%. isEchoMode stays false — PR tracking, gamification, and Old School behavior are preserved. EchoLevel.HARDER and warmupReps=3 (Constants.DEFAULT_WARMUP_REPS) are used for the Old School 0x4E path. Changes: - Models.kt: add hasEccentricOverload computed property - ActiveSessionEngine.kt: dispatch 0x4E for Old School+ecc>100, remove isEchoMode gate on defaults save, skip deload stall for ecc>100 - JustLiftScreen.kt: remove isEchoMode guard on LaunchedEffect, split Card to show eccentric dropdown for Old School (no EchoLevel) - SetReadyScreen.kt: split guard for eccentric slider (Echo+OldSchool), keep EchoLevel/AMRAP reps Echo-only - ExerciseEditBottomSheet.kt: show EccentricLoadSelector for Old School - RoutineOverviewScreen.kt: show eccentric load slider for Old School - RoutineFlowManager.kt: populate eccentricLoadPercent for Old School - WorkoutParametersTest.kt: 4 new hasEccentricOverload tests Closes #674
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 28355e4df5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
|
|
||
| val commandValidation = if (bleParams.isEchoMode) { | ||
| val hasEccentricOverload = bleParams.eccentricLoad.percentage > 100 |
There was a problem hiding this comment.
Restrict overload dispatch to Old School mode
When a user selects an overload above 100% in Echo or Old School and then switches to Pump, TUT, TUT Beast, or Eccentric Only, both JustLiftScreen and ExerciseConfigViewModel.onSelectedModeChange retain the previous eccentric value. This mode-agnostic check consequently sends the 0x4E Echo control packet instead of that mode's program packet and also disables deload auto-stop. Require ProgramMode.OldSchool here in addition to the percentage check.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in commit 1a02b59: hasEccentricOverload now requires ProgramMode.OldSchool in addition to eccentricLoad.percentage > 100. This prevents the 0x4E Echo packet from being dispatched when a user switches from Old School+130% to Pump/TUT/TUTBeast/EccentricOnly. The ActiveSessionEngine now uses the model property instead of an inline percentage-only check.
| if (isEchoMode || isOldSchool) { | ||
| EccentricLoadSelector( | ||
| eccentricLoad = eccentricLoad, | ||
| onLoadChange = viewModel::onEccentricLoadChange, | ||
| ) |
There was a problem hiding this comment.
Preserve Old School overload in portal routine sync
Old School routines can now save a selected overload locally, but PortalSyncAdapter.toPortalRoutine still emits eccentricLoad = null for every non-Echo exercise. After the routine is pushed and restored on another device, PortalPullAdapter.parseEccentricLoad(null) converts it to 100%, silently removing the configured overload and changing the workout behavior. Serialize this field for Old School as well as Echo.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in commit 1a02b59: PortalSyncAdapter.toPortalRoutine now serializes eccentricLoad for both ProgramMode.Echo and ProgramMode.OldSchool. Previously it was Echo-only, which silently dropped the Old School overload setting during portal sync and restore.
…ngs label The enhancement added an Old School-specific settings label. Update the source-level wiring test to match the new conditional pattern.
…al sync - hasEccentricOverload now requires ProgramMode.OldSchool (not just ecc%>100) so switching from Old School+130% to Pump/TUT doesn't dispatch 0x4E packet - ActiveSessionEngine uses the model property instead of inline percentage check - PortalSyncAdapter serializes eccentricLoad for Old School routines (not just Echo) - Updated tests: Echo+LOAD_130 now false; added Pump+LOAD_130 regression test Addresses Codex review P1s on PR #683
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1a02b592ca
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| val command = if (bleParams.isEchoMode || hasEccentricOverload) { | ||
| BlePacketFactory.createEchoControl( |
There was a problem hiding this comment.
Preserve the configured Old School weight in overload packets
When an Old School set uses more than 100% eccentric load, this branch replaces the 96-byte program frame with createEchoControl(). That 32-byte frame serializes reps, Echo timing/velocity, and eccentric percentage, but neither weightPerCableKg, progression, nor the Old School phase profile, so a freshly connected machine cannot receive the user's selected concentric weight and is configured as Echo rather than Old School. The overload path needs a protocol sequence or packet that retains the Old School force configuration instead of sending only the Echo frame.
Useful? React with 👍 / 👎.
| if (isEchoMode || isOldSchool) { | ||
| OverviewEccentricLoadSlider( | ||
| percent = eccentricLoadPercent, | ||
| onPercentChange = onEccentricLoadChange, |
There was a problem hiding this comment.
Apply the overview eccentric adjustment when starting
For an Old School routine, changing this newly visible slider only updates ExerciseOverviewAdjustments; startCurrentExercise() passes only adjusted weight and reps to enterSetReadyWithAdjustments(), which then restores both the SetReady percentage and WorkoutParameters.eccentricLoad from the saved exercise. Consequently, selecting (for example) 130% on the overview and pressing Start silently begins with the routine's original percentage. Pass the adjusted eccentric value through the start path alongside weight and reps.
Useful? React with 👍 / 👎.
| val isOldSchool = selectedMode is WorkoutMode.OldSchool | ||
| val showEccentricLoad = isEchoMode || isOldSchool | ||
|
|
||
| if (showEccentricLoad) { |
There was a problem hiding this comment.
Restrict Old School choices to supported overload values
When Old School is selected, this exposes the existing dropdown containing 0%, 50%, and 75% as well as overload values; the routine editor does the same, and the SetReady/overview sliders expose the full 0–150% range. However, hasEccentricOverload dispatches eccentric behavior only above 100%, so selecting any sub-100 value displays and persists an asymmetric-load choice while the machine receives the ordinary symmetric Old School program. Filter Old School controls to the supported 100%/110–150% choices or implement the advertised underload behavior.
Useful? React with 👍 / 👎.
…al sync - hasEccentricOverload now requires ProgramMode.OldSchool (not just ecc%>100) so switching from Old School+130% to Pump/TUT doesn't dispatch 0x4E packet - ActiveSessionEngine uses the model property instead of inline percentage check - PortalSyncAdapter serializes eccentricLoad for Old School only when > 100% - Updated tests: Echo+LOAD_130 now false; added Pump+LOAD_130 regression test Addresses Codex review P1s on PR #683
1a02b59 to
b5097ad
Compare
Summary
Adds eccentric load percentage support (110%–150%) to Old School mode by reusing the proven Echo 0x4E BLE packet mechanism. When eccentric load > 100%, the app dispatches the 0x4E packet with
EchoLevel.HARDERandwarmupReps = 3(Constants.DEFAULT_WARMUP_REPS).isEchoModestays false — PR tracking, gamification, and Old School behavior are preserved.Closes #674
Changes
Source (7 files)
Models.kthasEccentricOverloadcomputed propertyActiveSessionEngine.ktJustLiftScreen.ktSetReadyScreen.ktExerciseEditBottomSheet.ktRoutineOverviewScreen.ktRoutineFlowManager.ktTests (1 file, 4 new tests)
hasEccentricOverload true for Old School + LOAD_130hasEccentricOverload false for Old School + LOAD_100hasEccentricOverload false for Echo + LOAD_100hasEccentricOverload true for Echo + LOAD_130Behavior
User Instructions
Old School mode now shows an Eccentric Load dropdown in Just Lift, Set Ready, and the Routine Editor. Select 110%–150% to increase resistance during the lowering phase. PR tracking and gamification continue based on concentric weight.
Hardware Validation Gate
This implementation covers app-side changes only. Before production release, hardware validation must confirm:
eccentricMaxVelocity = -200.0produces correct eccentric limits