Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat (ui): implement speed controls #1206

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft

feat (ui): implement speed controls #1206

wants to merge 8 commits into from

Conversation

cpvalente
Copy link
Owner

No description provided.

Copy link
Contributor

coderabbitai bot commented Sep 2, 2024

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The changes introduce a new TimerSpeed component within the PlaybackControl functionality, allowing users to adjust the playback speed of events. A corresponding SCSS file provides styles for this component, enhancing its visual presentation. Additionally, new hooks and methods for managing timer speed are implemented in the socket and runtime service files, respectively, expanding the overall capabilities of the playback control interface.

Changes

File Change Summary
apps/client/src/features/control/playback/PlaybackControl.tsx Introduced TimerSpeed component into PlaybackControl, enhancing playback speed control.
apps/client/src/features/control/playback/timer-speed/TimerSpeed.module.scss Added styles for the TimerSpeed component, defining layout and visual presentation.
apps/client/src/features/control/playback/timer-speed/TimerSpeed.tsx Introduced TimerSpeed component with functionality for adjusting playback speed.
apps/common/hooks/useSocket.ts Added useTimerSpeed hook and setTimerSpeed object for managing timer speed via sockets.
apps/server/src/api-integration/integration.controller.ts Added new action handlers for speed management: get-speed, set-speed, and reset-speed.
apps/server/src/services/runtime-service/RuntimeService.ts Introduced methods for speed management: getSpeed, setSpeed, and resetSpeed.
apps/client/src/theme/ontimeButton.ts Removed fontWeight property from ontimeButtonSubtleWhite, altering its default styling.

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@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: 4

Outside diff range, codebase verification and nitpick comments (4)
apps/client/src/features/control/playback/PlaybackControl.tsx (1)

27-27: Ensure TimerSpeed component integration with PlaybackControl.

The TimerSpeed component is implemented as a standalone function without receiving any props. It contains internal logic but does not interact with the PlaybackControl component's state or functionality. Consider passing relevant props or connecting it to the parent component's state to ensure proper integration.

  • File: apps/client/src/features/control/playback/timer-speed/TimerSpeed.tsx
Analysis chain

Verify TimerSpeed integration with PlaybackControl.

The TimerSpeed component has been added to the JSX structure, which is good. However, it's not receiving any props, which might indicate that it's not fully integrated with the PlaybackControl component's state or functionality.

Please ensure that the TimerSpeed component is properly integrated with the PlaybackControl component. Consider if it needs to receive any props or interact with the parent component's state.

To verify the implementation of TimerSpeed, you can run the following script:

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the implementation of TimerSpeed component

# Test: Search for the TimerSpeed component implementation
ast-grep --lang typescript --pattern 'export default function TimerSpeed($_) {
  $$$
}'

# Test: Check if TimerSpeed is using any hooks or props
rg --type typescript 'function TimerSpeed' -A 10

Length of output: 175


Script:

#!/bin/bash
# Description: Check the implementation of TimerSpeed component

# Test: Search for the TimerSpeed component implementation using a broader pattern
ast-grep --lang typescript --pattern 'function TimerSpeed($_) {
  $$$
}'

# Test: Correct the file type and search for TimerSpeed usage
rg --type tsx 'function TimerSpeed' -A 10

Length of output: 146


Script:

#!/bin/bash
# Description: Locate and check the implementation of TimerSpeed component

# Locate files that might contain the TimerSpeed component
fd TimerSpeed --type f

# Search for TimerSpeed component implementation in located files
rg 'function TimerSpeed' -A 10

Length of output: 1259

apps/client/src/features/control/playback/timer-speed/TimerSpeed.module.scss (2)

19-34: LGTM: Speed container and regular speed indicator look good.

The .speedContainer and .speedRegular classes are well-structured to create a visual speed indicator.

Consider using CSS custom properties for values like 33.33% to make it easier to adjust in the future:

 .speedRegular {
   position: absolute;
   left: 0;
   height: 100%;
-  width: 33.33%;
+  width: var(--speed-regular-width, 33.33%);
   background-color: $ui-white;
 }

8-13: Unify .label styles across the codebase.

The .label class is defined in multiple SCSS files, suggesting potential inconsistencies in styling. Consider addressing the TODO comment by unifying these styles to ensure consistency across components. This could involve centralizing the styles in a common stylesheet or using a shared mixin.

  • Instances found in various files such as:
    • apps/client/src/features/operator/status-bar/StatusBar.module.scss
    • apps/client/src/features/viewers/timeline/TimelinePage.scss
    • apps/client/src/features/control/playback/timer-speed/TimerSpeed.module.scss
    • And others...
Analysis chain

Consider unifying panel labels as suggested by the TODO comment.

The .label class looks good, but there's a TODO comment about unifying panel labels. This might indicate a need for consistency across different components.

To check for consistency, let's search for similar label styles:

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for similar label styles across the codebase

# Test: Look for similar label styles. Expect: Consistent label styles across components.
rg --type scss -g '*.module.scss' '\.label\s*\{'

Length of output: 79


Script:

#!/bin/bash
# Description: Search for similar label styles across SCSS files

# Test: Look for similar label styles. Expect: Consistent label styles across components.
rg '\.label\s*\{' --glob '*.scss'

Length of output: 1095

apps/client/src/features/control/playback/timer-speed/TimerSpeed.tsx (1)

1-62: Summary of improvements needed:

  1. Extract and test the mapRange function.
  2. Implement state management for speed values.
  3. Complete the handler functions with actual logic.
  4. Refactor inline styles to SCSS module.
  5. Improve accessibility with ARIA labels and semantic HTML.
  6. Consider adding prop types or TypeScript interfaces for the component props.
  7. Add unit tests for the TimerSpeed component.

Overall, the component structure is good, but it needs refinement in functionality and best practices.

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between aa4ee54 and 3109f3a.

Files selected for processing (4)
  • apps/client/src/features/control/playback/PlaybackControl.tsx (2 hunks)
  • apps/client/src/features/control/playback/timer-speed/TimerSpeed.module.scss (1 hunks)
  • apps/client/src/features/control/playback/timer-speed/TimerSpeed.tsx (1 hunks)
  • apps/client/src/theme/ontimeButton.ts (1 hunks)
Files skipped from review due to trivial changes (1)
  • apps/client/src/theme/ontimeButton.ts
Additional comments not posted (7)
apps/client/src/features/control/playback/PlaybackControl.tsx (2)

9-9: LGTM: TimerSpeed import added correctly.

The import statement for the new TimerSpeed component is properly placed and follows the existing import style in the file.


Line range hint 13-30: Verify the purpose and impact of TimerSpeed in PlaybackControl.

The addition of TimerSpeed enhances the functionality of the PlaybackControl component without disrupting the existing structure, which is good. However, it's important to ensure that this addition aligns with the component's overall purpose.

Please consider the following:

  1. Does TimerSpeed fit logically within the PlaybackControl component?
  2. Is there any potential impact on performance or user experience?
  3. Should TimerSpeed interact with other components like PlaybackButtons or PlaybackTimer?

To help verify these considerations, you can run the following script:

Verification successful

Integration of TimerSpeed in PlaybackControl Verified

The TimerSpeed component is well-integrated into the PlaybackControl component. It operates with its own internal logic and event handlers, fitting logically within the existing structure without disrupting other components. While no performance optimization techniques were found, this does not impact the current integration. Consider exploring optimizations like React.memo or useMemo if performance becomes a concern.

  • PlaybackControl uses usePlaybackControl for state management.
  • TimerSpeed has its own handlers: handleApply, handleReset, handleMeetSchedule.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Analyze the PlaybackControl component and its children

# Test: Check for any shared state or props between components
rg --type typescript 'const \w+ = use\w+' apps/client/src/features/control/playback

# Test: Look for any performance optimization techniques
rg --type typescript 'React.memo|useMemo|useCallback' apps/client/src/features/control/playback

# Test: Check for any event handlers or functions that might be shared
rg --type typescript 'function \w+\(|const \w+ = \(' apps/client/src/features/control/playback

Length of output: 385


Script:

#!/bin/bash
# Description: Analyze the PlaybackControl component and its children

# Test: Check for any shared state or props between components
rg --glob '*.tsx' 'const \w+ = use\w+' apps/client/src/features/control/playback

# Test: Look for any performance optimization techniques
rg --glob '*.tsx' 'React.memo|useMemo|useCallback' apps/client/src/features/control/playback

# Test: Check for any event handlers or functions that might be shared
rg --glob '*.tsx' 'function \w+\(|const \w+ = \(' apps/client/src/features/control/playback

Length of output: 3075

apps/client/src/features/control/playback/timer-speed/TimerSpeed.module.scss (4)

1-6: LGTM: Panel container layout looks good.

The .panelContainer class is well-structured using flexbox for layout with appropriate spacing.


15-17: LGTM: Highlight class is simple and effective.

The .highlight class correctly sets the color for emphasized text.


36-42: LGTM: Speed override class is well-implemented.

The .speedOverride class effectively uses a CSS custom property for dynamic sizing, which is a good practice for flexibility and maintainability.


44-69: LGTM with a note: Labels styling is comprehensive, but consider edge cases.

The .labels class and its nested elements are well-structured for positioning and styling label elements.

There's a TODO comment about accounting for the case where we translate all the way left. This edge case should be addressed:

Consider adding a minimum left position to prevent labels from going off-screen:

 .labels {
   // ... existing styles ...
   
   > span {
     position: absolute;
     transform: translateX(-50%);
+    min-left: 0; // Prevent labels from going off-screen
   }
   
   // ... rest of the styles ...
 }
apps/client/src/features/control/playback/timer-speed/TimerSpeed.tsx (1)

1-3: LGTM: Imports look good.

The necessary components and styles are imported correctly.

Comment on lines +5 to +8
// TODO: extract and test
function mapRange(value: number, fromA_start: number, fromA_end: number, toB_start: number, toB_end: number): number {
return ((value - fromA_start) * (toB_end - toB_start)) / (fromA_end - fromA_start) + toB_start;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Address TODO: Extract and test mapRange function.

The mapRange function should be moved to a separate utility file and unit tested.

Would you like me to create a new utility file for this function and generate unit tests? I can also open a GitHub issue to track this task if you prefer.

Comment on lines 28 to 61
return (
<div className={style.panelContainer}>
<div className={style.label}>Timer speed</div>
<div style={{ display: 'flex', gap: '1rem' }}>
<Button size='sm' variant='ontime-subtle-white' onClick={handleApply}>
Apply
</Button>
<Button size='sm' variant='ontime-subtle-white' onClick={handleReset}>
Reset
</Button>
<Button size='sm' variant='ontime-subtle-white' onClick={handleMeetSchedule}>
Meet schedule
</Button>
</div>
<div>
<span>1.0x</span>
<span>{'->'}</span>
<span className={style.highlight}>{`${newSpeed}x`}</span>
</div>
<div>
<div className={style.speedContainer}>
<div className={style.speedOverride} style={{ '--override': newSpeedIndicator }} />
<div className={style.speedRegular} />
</div>
<div className={style.labels}>
<span className={style.override} style={{ left: '66%' }}>{`${newSpeed}x`}</span>
<span>0.5x</span>
<span style={{ left: '33.33%' }}>1.0x</span>
<span style={{ left: '66.66%' }}>1.5x</span>
<span style={{ left: '100%' }}>2.0x</span>
</div>
</div>
</div>
);
Copy link
Contributor

Choose a reason for hiding this comment

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

Improve component structure and accessibility.

  1. Move inline styles to the SCSS module:
-      <div style={{ display: 'flex', gap: '1rem' }}>
+      <div className={style.buttonContainer}>

Then add to your SCSS module:

.buttonContainer {
  display: flex;
  gap: 1rem;
}
  1. Add aria labels to improve accessibility:
-        <Button size='sm' variant='ontime-subtle-white' onClick={handleApply}>
+        <Button size='sm' variant='ontime-subtle-white' onClick={handleApply} aria-label="Apply new speed">
           Apply
         </Button>

Make similar changes for the other buttons.

  1. Consider using semantic HTML elements where appropriate, such as <header> for the "Timer speed" label.

Comment on lines 16 to 26
const handleApply = () => {
console.log('timerSpeedControl.apply');
};

const handleReset = () => {
console.log('timerSpeedControl.apply');
};

const handleMeetSchedule = () => {
console.log('timerSpeedControl.apply');
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Implement handler functions.

The handler functions currently only log to the console. Implement the actual functionality for applying speed changes, resetting, and meeting the schedule.

Example for handleApply:

   const handleApply = () => {
-    console.log('timerSpeedControl.apply');
+    // TODO: Implement logic to apply the new speed
+    // For example:
+    // applyNewSpeed(newSpeed);
   };

Make similar changes for handleReset and handleMeetSchedule.

Committable suggestion was skipped due to low confidence.

Comment on lines 10 to 15
export default function TimerSpeed() {
const newSpeed = 1.23;
const newSpeedIndicator = mapRange(newSpeed, 0.5, 2.0, 0, 100);

console.log('newSpeedIndicator', newSpeedIndicator);

Copy link
Contributor

Choose a reason for hiding this comment

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

Replace hardcoded values with state management.

The newSpeed value is hardcoded, and newSpeedIndicator is calculated based on it. Consider using React state to manage these values dynamically.

-  const newSpeed = 1.23;
-  const newSpeedIndicator = mapRange(newSpeed, 0.5, 2.0, 0, 100);
+  const [newSpeed, setNewSpeed] = useState(1.0);
+  const newSpeedIndicator = useMemo(() => mapRange(newSpeed, 0.5, 2.0, 0, 100), [newSpeed]);

Also, remove the console.log statement or replace it with proper error logging.

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export default function TimerSpeed() {
const newSpeed = 1.23;
const newSpeedIndicator = mapRange(newSpeed, 0.5, 2.0, 0, 100);
console.log('newSpeedIndicator', newSpeedIndicator);
export default function TimerSpeed() {
const [newSpeed, setNewSpeed] = useState(1.0);
const newSpeedIndicator = useMemo(() => mapRange(newSpeed, 0.5, 2.0, 0, 100), [newSpeed]);

Copy link
Contributor

@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: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 3109f3a and df57bdd.

Files selected for processing (2)
  • apps/client/src/features/control/playback/timer-speed/TimerSpeed.module.scss (1 hunks)
  • apps/client/src/features/control/playback/timer-speed/TimerSpeed.tsx (1 hunks)
Files skipped from review due to trivial changes (1)
  • apps/client/src/features/control/playback/timer-speed/TimerSpeed.module.scss
Files skipped from review as they are similar to previous changes (1)
  • apps/client/src/features/control/playback/timer-speed/TimerSpeed.tsx

Copy link
Contributor

@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: 4

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between df57bdd and 3226688.

Files selected for processing (4)
  • apps/client/src/common/hooks/useSocket.ts (1 hunks)
  • apps/client/src/features/control/playback/timer-speed/TimerSpeed.tsx (1 hunks)
  • apps/server/src/api-integration/integration.controller.ts (1 hunks)
  • apps/server/src/services/runtime-service/RuntimeService.ts (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • apps/client/src/features/control/playback/timer-speed/TimerSpeed.tsx
Additional comments not posted (2)
apps/client/src/common/hooks/useSocket.ts (2)

117-123: LGTM!

The code changes are approved.


125-129: LGTM!

The code changes are approved.

Comment on lines 242 to 255
/* Speed */
'get-speed': () => {
const factor = runtimeService.getSpeed();
return { payload: factor };
},
'set-speed': (payload) => {
// TODO: validate payload type
const factor = runtimeService.setSpeed(payload as number);
return { payload: factor };
},
'reset-speed': () => {
const factor = runtimeService.resetSpeed();
return { payload: factor };
},
Copy link
Contributor

Choose a reason for hiding this comment

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

LGTM! Address the TODO comment.

The code changes are approved. The new action handlers are correctly implemented and follow the existing pattern of the actionHandlers object.

Please address the TODO comment in the set-speed handler to validate the payload type.

Do you want me to generate the payload validation code or open a GitHub issue to track this task?

Comment on lines 651 to 655
public getSpeed(): number {
// TODO: call function that calculates speed factor
console.log('runtimeService.getSpeed');
return 0;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Implement the speed calculation logic.

The getSpeed method is currently a placeholder that needs to be implemented to calculate the speed factor based on the remaining time and task duration.

Consider the following steps to implement the speed calculation logic:

  1. Retrieve the current time and the expected end time of the task.
  2. Calculate the remaining time by subtracting the current time from the end time.
  3. Retrieve the remaining duration of the task.
  4. Calculate the speed factor by dividing the remaining duration by the remaining time.
  5. Return the calculated speed factor.

For example:

public getSpeed(): number {
  const currentTime = Date.now();
  const endTime = /* retrieve end time */;
  const remainingTime = endTime - currentTime;
  const remainingDuration = /* retrieve remaining duration */;
  const speedFactor = remainingDuration / remainingTime;
  return speedFactor;
}

Comment on lines 662 to 669
public setSpeed(time: number): number {
// TODO: validate state
// TODO: validate value
// TODO: call mutating function in state
console.log('runtimeService.setSpeed', time);
// TODO: return speed factor after mutating
return 0;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Implement the missing logic for setting the speed.

The setSpeed method needs to be implemented to validate the input, mutate the state, and return the applied speed factor. Consider the following suggestions:

  1. Validate the current state to ensure that setting the speed is allowed (e.g., check if a task is currently running).
  2. Validate the input time value to ensure it is within an acceptable range.
  3. Call a mutating function to update the speed factor in the state based on the input time.
  4. Return the applied speed factor after the mutation.

Here's an example of how the method could be implemented:

public setSpeed(time: number): number {
  // Validate the current state
  if (!this.isTaskRunning()) {
    throw new Error('No task is currently running');
  }

  // Validate the input time value
  if (time <= 0) {
    throw new Error('Time must be a positive value');
  }

  // Call a mutating function to update the speed factor
  const speedFactor = this.updateSpeedFactor(time);

  // Return the applied speed factor
  return speedFactor;
}

Make sure to implement the necessary validation and mutation logic based on your specific requirements.

Comment on lines 675 to 681
public resetSpeed(): number {
// TODO: validate state
// TODO: call mutating function in state
console.log('runtimeService.resetSpeed');
// TODO: return speed factor after mutating
return 1.0;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Implement the missing logic for resetting the speed.

The resetSpeed method needs to be implemented to validate the state, reset the speed factor to 1, and return the updated value. Consider the following suggestions:

  1. Validate the current state to ensure that resetting the speed is allowed (e.g., check if a task is currently running).
  2. Call a mutating function to reset the speed factor to 1 in the state.
  3. Return the updated speed factor after the mutation.

Here's an example of how the method could be implemented:

public resetSpeed(): number {
  // Validate the current state
  if (!this.isTaskRunning()) {
    throw new Error('No task is currently running');
  }

  // Call a mutating function to reset the speed factor
  const speedFactor = this.resetSpeedFactor();

  // Return the updated speed factor
  return speedFactor;
}

Make sure to implement the necessary validation and mutation logic based on your specific requirements.

@cpvalente cpvalente marked this pull request as draft September 3, 2024 08:47
return runtimeState.timer.speed;
}

export function calculateSpeed() {
Copy link
Owner Author

Choose a reason for hiding this comment

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

please dont see these as answers, but as suggestions

Right now, we are attaching the functionality of time manipulation to a target time. I believe that we should not make the feature in a way that would stop us from doing some time manipulation on its own (ie, set timer to 1.2x)

With this assumption, this is a utility function that gives me the speed that I would need to finish on time. without making mutations to state.
With this in mind

// TODO: what should this return if no timer is running?

Good question.
Considering this as a utility function, I believe the appropriate behaviour is to give me a result, or a reason not to do so. In that case, it is appropriate to throw when the operation is invalid

// TODO: this can produce negative speeds (i.e. the desired finish time is in the past)
// TODO: should there be some clamping or rounding on this number?

I dont think we should do rounding.
Following the previous rule, I believe that we should throw if the desired finish time is in the past

Copy link
Collaborator

Choose a reason for hiding this comment

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

calculateSpeed does exactly that, simply returns the speed factor necessary to finish on the timer scheduled end. The user would then need to apply that speed factor (or any other speed factor they want). As far as the clamping/rounding the function can return something like 1.234567898765432 I guess the precision is probably "free" to carry around just might only need truncated in displaying to the user.

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.

2 participants