Skip to content

Implement a segment time component.#264

Merged
CryZe merged 3 commits intoLiveSplit:masterfrom
DarkRTA:segment-time-component
Nov 29, 2019
Merged

Implement a segment time component.#264
CryZe merged 3 commits intoLiveSplit:masterfrom
DarkRTA:segment-time-component

Conversation

@DarkRTA
Copy link
Copy Markdown
Contributor

@DarkRTA DarkRTA commented Oct 30, 2019

This draft PR contains initial work for implementing a segment time component. This is far from merge ready right now but the final plan is to have it act similarly to the segment time display on the detailed timer.

One thing that needs to be decided on is the name of the key for display on the layout. Right now it is simply named "Segment Time" but I feel like this could be a lot more descriptive. Currently my plan is to show the comparison in parenthesis if it differs from the timer's current comparison.

Also I'm not sure if I documented everything correctly either.

Closes #259

@CryZe CryZe added enhancement An improvement for livesplit-core. feature A new user visible feature for livesplit-core. needs further discussion It is unclear how to progress without making further decisions. labels Oct 30, 2019
@CryZe CryZe requested a review from wooferzfg October 30, 2019 21:21
@DarkRTA
Copy link
Copy Markdown
Contributor Author

DarkRTA commented Oct 30, 2019

One thing that needs to be decided on is the name of the key for display on the layout. Right now it is simply named "Segment Time" but I feel like this could be a lot more descriptive. Currently my plan is to show the comparison in parenthesis if it differs from the timer's current comparison.

For this I've decided to just do what the Previous Segment component does here.

ie: Segment Time (PB) if the comparison is set to "Personal Best"

@DarkRTA DarkRTA force-pushed the segment-time-component branch from e4c0d3f to 3f0b226 Compare October 31, 2019 00:39
@DarkRTA
Copy link
Copy Markdown
Contributor Author

DarkRTA commented Oct 31, 2019

The component itself is fully functional now but some code cleanup is needed.

The last thing we should ask is if we should provide a timing method override.
I'm split between providing one to match the detailed timer or not providing one for consistency with the other components.

If we do provide one we'll also need some way to indicate it on the layout so I'm leaning on the side of not having it.

@CryZe
Copy link
Copy Markdown
Collaborator

CryZe commented Oct 31, 2019

I believe we want to have more specialized key names, such as "Best Segment Time", "Worst Segment Time", "Average Segment Time" (and possibly more).

@CryZe
Copy link
Copy Markdown
Collaborator

CryZe commented Oct 31, 2019

I added a commit with some of these changes and TODO comments about changes that still need to be done.

@DarkRTA DarkRTA force-pushed the segment-time-component branch from bfc2328 to 7b203e5 Compare October 31, 2019 22:52
@wooferzfg
Copy link
Copy Markdown
Member

I think it might be good to have an option (that is on by default) to switch to a live segment time whenever your current segment is longer than the comparison segment. That would make this component consistent with pretty much every other component we have.

@DarkRTA
Copy link
Copy Markdown
Contributor Author

DarkRTA commented Nov 1, 2019

I think it might be good to have an option (that is on by default) to switch to a live segment time whenever your current segment is longer than the comparison segment.

The original intent here was to be identical to how the segment times are on the detailed timer but that might not be a bad thing to add.

@DarkRTA
Copy link
Copy Markdown
Contributor Author

DarkRTA commented Nov 3, 2019

@CryZe, I hit a bit of a roadblock when it comes to moving calculate_comparison_time into the analysis module and I want your opinion on the best course of action to take here.

Right now I've have 3 good options:

  1. Remove calculate_comparison_time from the component entirely and use comparison_segment_time from the analysis module.
  2. Move it into the analysis module under the name calculate_segment_time
  3. Leave it as-is.

Option 1 seems like the best course of action but it won't do exactly what we want. (It'll combine segments if there is an empty split instead of returning None. This is consistent with the splits component though)

Option 2 results in 2 functions with almost identical purpose in the analysis module. In addition, the name also conflicts with something defined in the detailed timer so we'll have to rename that.

Option 3 just results in duplicated code.

Edit: Upon giving this another thought, we should just go with Option 1 because we don't need to match the detailed timer exactly here. After this, it should be merge ready unless we want to implement the feature @wooferzfg suggested.

@DarkRTA DarkRTA force-pushed the segment-time-component branch from 7ba5035 to eb4e2c4 Compare November 3, 2019 23:48
@DarkRTA DarkRTA marked this pull request as ready for review November 3, 2019 23:48
@DarkRTA DarkRTA force-pushed the segment-time-component branch from eb4e2c4 to f0e315d Compare November 3, 2019 23:49
Copy link
Copy Markdown
Collaborator

@CryZe CryZe left a comment

Choose a reason for hiding this comment

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

This mostly seems close to being done though. Good job so far :D

@DarkRTA DarkRTA force-pushed the segment-time-component branch from f0e315d to 241ebf0 Compare November 4, 2019 15:37
Comment on lines 71 to 73
pub fn comparison_segment_time(
run: &Run,
segment_index: usize,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This function should have the additional checks that the detailed timer is doing, such as the specialized logic for the best segments comparison and so on. The goal should be to remove the function from the detailed timer and use this one instead. Then it should be good to merge.

Copy link
Copy Markdown
Collaborator

@CryZe CryZe Nov 8, 2019

Choose a reason for hiding this comment

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

@wooferzfg Looks like in the splits we use "combined comparison segment time", in the detailed timer we use "single comparison segment time" and for the segment time component it could potentially be either. What do you think we should do? Do the same thing for all of them? (the difference being that skipped splits get combined together, while the detailed timer just shows a - then).

Copy link
Copy Markdown
Member

@wooferzfg wooferzfg Nov 8, 2019

Choose a reason for hiding this comment

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

My initial reasoning for using the combined segment time in the splits vs. a single segment time in the detailed timer is that you can see all of the segments in the splits, which means you know which segment the combined segment time started at.

In the detailed timer, you can only see the current segment, so we never show combined segments. There's also the issue of the segment timer starting at a different segment than the comparison segment time if we start combining stuff. For example, you might get a case where the segment timer is at 5 minutes, the PB comparison segment time is 40 minutes (because it's combined), and the second comparison segment time is 2 hours (because it's also combined, but starting from an earlier segment). That makes it look like you can save a lot of time, but in reality that's not necessarily true.

However, we don't really apply this logic everywhere else, so it's not totally clear what we should do here. The previous segment component uses combined segments, for example. In my opinion, it would be best to use the combined comparison segment time here because there's only one piece of information being displayed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Yeah I think for the splits it makes sense to keep it showing the combined segments, as you can see that the ones before are skipped. For the detailed timer you don't, so it makes sense to dash it out. But I'm not quite following your argument for the segment time component, as you seem to argue the opposite there?

combined comparison segment time here because there's only one piece of information being displayed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For the segment time component, we only show one value, so there's no issue with conflicting information within the component (unlike the detailed timer, where we show a segment timer and 2 different comparisons). I don't feel too strongly about this though.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I don't have many strong feelings here either, but if I was forced to choose I'd say just unify them for the sake of code quality and consistency.

@CryZe CryZe removed the needs further discussion It is unclear how to progress without making further decisions. label Nov 7, 2019
@DarkRTA
Copy link
Copy Markdown
Contributor Author

DarkRTA commented Nov 8, 2019

Looks like this is should be good to merge now. Before we merge this, I'm going to squash 241ebf0 and 81faae3 so the commit history is cleaner.

@DarkRTA DarkRTA force-pushed the segment-time-component branch from e7ea62b to e3d4530 Compare November 8, 2019 16:48
///
/// Panics if the provided `segment_index` is greater than or equal to
/// `run.len()`.
pub fn comparison_segment_time(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think that the current implementation of this method makes sense.

  • This provides a combined segment time, which means that the detailed timer's logic will change when switching over to it.
  • Using the best segment time only makes sense if we're using non-combined segment times (because, by definition, the best segment time is a non-combined segment time). That's why the detailed timer was using it previously, but the splits component was not.

Copy link
Copy Markdown
Collaborator

@CryZe CryZe Nov 9, 2019

Choose a reason for hiding this comment

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

Yeah, this wasn't meant to be considered finished.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would prefer if there were two separate methods in state_helper: one for combined segment times and one for non-combined segment times. The non-combined segment time method would do the best segment time override, while the combined segment time method would not. The splits component would use the combined segment time method, and the detailed timer component would use the non-combined segment time method. The segment time component would use whichever one we think makes the most sense (which is the discussion we just had in the other thread that didn't reach a clear answer).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

So if we end up splitting comparison segment time into two distinct methods and splits keep using the combined one, then there's no way for the splits to show the best segment times as a column. Are we sure that's what we want? Is there a disadvantage to just switch to the best segment times despite us usually showing combined segment times? The problem is that just like best split times and co. we can't really derive any segment times from it, as the times aren't truly building on top of each other.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Personally I'd prefer just having a single method and explicitly handling empty segments in the detailed timer itself if the resulting code is cleaner than having 2 different methods with almost identical code.

Copy link
Copy Markdown
Member

@wooferzfg wooferzfg Nov 9, 2019

Choose a reason for hiding this comment

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

Eh, I guess it's fine to use the best segment times then, even if it's a little inconsistent.

Also, I agree on having a single method if you're able to cleanly keep the current logic of the detailed timer while using this method.

Copy link
Copy Markdown
Contributor Author

@DarkRTA DarkRTA Nov 10, 2019

Choose a reason for hiding this comment

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

Looks like we might actually have to have 2 different functions.

The cleanest way I can think of handling things in the detailed timer is to use a wrapper function and at that point we might as well just have 2 functions.

Update: In the end I went with the solution of having 2 different functions. I couldn't find a way to cleanly keep the current behavior of the detailed timer without creating a wrapper function (Mostly because my rust skills are quite lacking)

@CryZe
Copy link
Copy Markdown
Collaborator

CryZe commented Nov 15, 2019

I'll try to review and finish this on the weekend. (Although there's so many other things I still need to do, I'm not sure if I'll actually get to it)

@CryZe CryZe force-pushed the segment-time-component branch from 3e641b0 to aee4383 Compare November 22, 2019 11:25
@DarkRTA
Copy link
Copy Markdown
Contributor Author

DarkRTA commented Nov 29, 2019

@CryZe, This has been sitting idle for about 2 weeks so I'm wondering if you have found time to review this yet.

Co-authored-by: Christopher Serr <christopher.serr@gmail.com>
CryZe and others added 2 commits November 29, 2019 11:35
Now everything is using the same logic for the comparison segment time.
However there is the notion of a combined and single segment time. The
detailed timer used single segment time, while the others used combined
segment time. It's not clear yet what we want. Also for the segment time
component, this should possibly even be a setting.
We explicitly provide different functions for these to highlight the
differences. For the splits component we keep using the combined segment
times while for the Detailed Timer and Segment Time component we use
single segment times. The reason for this is that the Splits component
shows which splits have been skipped and are part of the combined
segment time, while the Detailed Timer and Segment Time component lack
this information.
@CryZe CryZe force-pushed the segment-time-component branch from aee4383 to 81b5ada Compare November 29, 2019 11:59
@CryZe CryZe merged commit 282ad83 into LiveSplit:master Nov 29, 2019
@CryZe CryZe added this to the v0.12 milestone Nov 29, 2019
@DarkRTA DarkRTA deleted the segment-time-component branch December 1, 2019 00:14
CryZe added a commit that referenced this pull request Nov 14, 2021
- Runs now support custom variables that are key value pairs that either the
  user can specify in the run editor or are provided by a script like an auto
  splitter. [#201](#201)
- There is now an option in the run editor to generate a comparison based on a
  user specified goal time. This uses the same algorithm as the `Balanced PB`
  comparison but with the time specified instead of the personal best.
  [#209](#209)
- Images internally are now stored as is without being reencoded as Base64 which
  was done before in order to make it easier for the web LiveSplit One to
  display them. [#227](#227)
- The Splits.io API is now available under the optional `networking` feature.
  [#236](#236)
- All key value based components share the same component state type now.
  [#257](#257)
- The crate now properly supports `wasm-bindgen` and `WASI`.
  [#263](#263)
- There is now a dedicated component for displaying the comparison's segment
  time. [#264](#264)
- Compiling the crate without `std` is now supported. Most features are not
  supported at this time though.
  [#270](#270)
- [`Splitterino`](https://github.com/prefixaut/splitterino) splits can now be
  parsed. [#276](#276)
- The `Timer` component can now show a segment timer instead.
  [#288](#288)
- Gamepads are now supported on the web.
  [#310](#310)
- The underlying "skill curve" that the `Balanced PB` samples is now exposed in
  the API. [#330](#330)
- The layout states can now be updated, which means almost all of the
  allocations can be reused from the previous frame. This is a lot faster.
  [#334](#334)
- In order to calculate a layout state, the timer now provides a snapshot
  mechanism that ensures that the layout state gets calculated at a fixed point
  in time. [#339](#339)
- Text shaping is now done via `rustybuzz` which is a port of `harfbuzz`.
  [#378](#378)
- Custom fonts are now supported.
  [#385](#385)
- The renderer is not based on meshes anymore that are suitable for rendering
  with a 3D graphics API. Instead the renderer is now based on paths, which are
  suitable for rendering with a 2D graphics API such as Direct2D, Skia, HTML
  Canvas, and many more. The software renderer is now based on `tiny-skia` which
  is so fast that it actually outperforms any other rendering and is the
  recommended way to render.
  [#408](#408)
- Remove support for parsing `worstrun` splits. `worstrun` doesn't support
  splits anymore, so `livesplit-core` doesn't need to keep its parsing support.
  [#411](#411)
- Remove support for parsing `Llanfair 2` splits. `Llanfair 2` was never
  publicly available and is now deleted entirely.
  [#420](#420)
- Hotkeys are now supported on macOS.
  [#422](#422)
- The renderer is now based on two layers. A bottom layer that rarely needs to
  be rerendered and the top layer that needs to be rerendered on every frame.
  Additionally the renderer is now a scene manager which manages a scene that an
  actual rendering backend can then render out.
  [#430](#430)
- The hotkeys are now based on the [UI Events KeyboardEvent code
  Values](https://www.w3.org/TR/uievents-code/) web standard.
  [#440](#440)
- Timing is now based on `CLOCK_BOOTTIME` on Linux and `CLOCK_MONOTONIC` on
  macOS and iOS. This ensures that all platforms keep tracking time while the
  operating system is in a suspended state.
  [#445](#445)
- Segment time columns are now formatted as segment times.
  [#448](#448)
- Hotkeys can now be resolved to the US keyboard layout.
  [#452](#452)
- They hotkeys are now based on `keydown` instead of `keypress` in the web.
  `keydown` handles all keys whereas `keypress` only handles visual keys and is
  also deprecated. [#455](#455)
- Hotkeys can now be resolved to the user's keyboard layout on both Windows and
  macOS. [#459](#459) and
  [#460](#460)
- The `time` crate is now used instead of `chrono` for keeping track of time.
  [#462](#462)
- The scene manager now caches a lot more information. This improves the
  performance a lot as it does not need to reshape the text on every frame
  anymore, which is a very expensive operation.
  [#466](#466) and
  [#467](#467)
- The hotkeys on Linux are now based on `evdev`, which means Wayland is now
  supported. Additionally the hotkeys are not consuming the key press anymore.
  [#474](#474)
- When holding down a key, the hotkey doesn't repeat anymore on Linux, macOS and
  WebAssembly. The problem still occurs on Windows at this time.
  [#475](#475) and
  [#476](#476)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement An improvement for livesplit-core. feature A new user visible feature for livesplit-core.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Possibly implement a Segment Time Component

3 participants