Repository: LiveSplit/livesplit-core (rust)

Issue:
Run Fixing Algorithms when opening splits

Pull request description:
Run Fixing Algorithms when opening splits
closes #21

edit: I'm probably missing something here. All of the tests are still passing on my machine though.

Patch:
diff --git a/src/run/editor/mod.rs b/src/run/editor/mod.rs
index e3c6a7e..3de8778 100644
--- a/src/run/editor/mod.rs
+++ b/src/run/editor/mod.rs
@@ -80,7 +80,8 @@ pub struct Editor {
 impl Editor {
     /// Creates a new Run Editor that modifies the Run provided. Creation of the
     /// Run Editor fails when a Run with no segments is provided.
-    pub fn new(run: Run) -> Result<Self, OpenError> {
+    pub fn new(mut run: Run) -> Result<Self, OpenError> {
+        run.fix_splits();
         let len = run.len();
         if len == 0 {
             return Err(OpenError::EmptyRun);
diff --git a/src/timing/timer/mod.rs b/src/timing/timer/mod.rs
index 3472241..2522234 100644
--- a/src/timing/timer/mod.rs
+++ b/src/timing/timer/mod.rs
@@ -81,6 +81,7 @@ impl Timer {
             return Err(CreationError::EmptyRun);
         }
 
+        run.fix_splits();
         run.regenerate_comparisons();
         let now = TimeStamp::now();
 
@@ -134,6 +135,7 @@ impl Timer {
             self.current_comparison = personal_best::NAME.to_string();
         }
 
+        run.fix_splits();
         run.regenerate_comparisons();
 
         Ok(mem::replace(&mut self.run, run))


Test patch:
diff --git a/src/run/editor/tests/mod.rs b/src/run/editor/tests/mod.rs
index 8194f2a..a2deca8 100644
--- a/src/run/editor/tests/mod.rs
+++ b/src/run/editor/tests/mod.rs
@@ -1,4 +1,5 @@
 use super::Editor;
+use crate::tests_helper::{create_timer, run_with_splits};
 use crate::{Run, Segment};
 
 mod comparison;
@@ -87,3 +88,26 @@ fn select_additionally_oob() {
 
     editor.select_additionally(1);
 }
+
+#[test]
+fn fix_run_upon_creation() {
+    let mut timer = create_timer(&["A", "B"]);
+    run_with_splits(&mut timer, &[3.0, 6.0]);
+    run_with_splits(&mut timer, &[2.0, 4.0]);
+    let mut run = timer.into_run(true);
+
+    // We pop the last attempt from the history, but keep it in the segment
+    // history, which makes the segment history elements unattached.
+    run.attempt_history.pop().unwrap();
+
+    // This should cause the run to be fixed.
+    let run = Editor::new(run).unwrap().close();
+
+    let segments = run.segments();
+
+    assert_eq!(segments[0].segment_history().try_get_min_index(), Some(0));
+    assert_eq!(segments[0].segment_history().try_get_max_index(), Some(1));
+
+    assert_eq!(segments[1].segment_history().try_get_min_index(), Some(0));
+    assert_eq!(segments[1].segment_history().try_get_max_index(), Some(1));
+}
diff --git a/src/run/tests/fixing.rs b/src/run/tests/fixing.rs
index 1e00197..44236ff 100644
--- a/src/run/tests/fixing.rs
+++ b/src/run/tests/fixing.rs
@@ -1,4 +1,5 @@
 use crate::tests_helper::{create_timer, run_with_splits};
+use crate::Timer;
 
 #[test]
 fn reattaches_unattached_segment_history_elements_by_using_negative_ids() {
@@ -21,3 +22,54 @@ fn reattaches_unattached_segment_history_elements_by_using_negative_ids() {
     assert_eq!(segments[1].segment_history().try_get_min_index(), Some(0));
     assert_eq!(segments[1].segment_history().try_get_max_index(), Some(1));
 }
+
+// The below tests should be in crate::timing::timer::tests, but we ended up
+// having to put them here due to run.attempt_history being private.
+
+#[test]
+fn timer_fix_run_upon_creation() {
+    let mut timer = create_timer(&["A", "B"]);
+    run_with_splits(&mut timer, &[3.0, 6.0]);
+    run_with_splits(&mut timer, &[2.0, 4.0]);
+    let mut run = timer.into_run(true);
+
+    // We pop the last attempt from the history, but keep it in the segment
+    // history, which makes the segment history elements unattached.
+    run.attempt_history.pop().unwrap();
+
+    // This should cause the run to be fixed.
+    let run = Timer::new(run).unwrap().into_run(true);
+
+    let segments = run.segments();
+
+    assert_eq!(segments[0].segment_history().try_get_min_index(), Some(0));
+    assert_eq!(segments[0].segment_history().try_get_max_index(), Some(1));
+
+    assert_eq!(segments[1].segment_history().try_get_min_index(), Some(0));
+    assert_eq!(segments[1].segment_history().try_get_max_index(), Some(1));
+}
+
+#[test]
+fn timer_fix_run_upon_replacement() {
+    let mut timer = create_timer(&["A", "B"]);
+    run_with_splits(&mut timer, &[3.0, 6.0]);
+    run_with_splits(&mut timer, &[2.0, 4.0]);
+    let mut run = timer.into_run(true);
+
+    // We pop the last attempt from the history, but keep it in the segment
+    // history, which makes the segment history elements unattached.
+    run.attempt_history.pop().unwrap();
+
+    // This should cause the run to be fixed.
+    let mut timer = create_timer(&["A", "B"]);
+    timer.set_run(run).unwrap();
+    let run = timer.into_run(true);
+
+    let segments = run.segments();
+
+    assert_eq!(segments[0].segment_history().try_get_min_index(), Some(0));
+    assert_eq!(segments[0].segment_history().try_get_max_index(), Some(1));
+
+    assert_eq!(segments[1].segment_history().try_get_min_index(), Some(0));
+    assert_eq!(segments[1].segment_history().try_get_max_index(), Some(1));
+}