[longomatch] Fix events resynchronization after syncing periods



commit b990a6ea55403a2497b11e24c7107d6df9d1ffb4
Author: Andoni Morales Alastruey <ylatuya gmail com>
Date:   Tue Apr 28 20:07:09 2015 +0200

    Fix events resynchronization after syncing periods

 LongoMatch.Core/Store/Period.cs                    |    9 +-
 LongoMatch.Core/Store/Project.cs                   |   48 ++++++++++++
 .../CanvasObjects/Dashboard/TimerObject.cs         |    1 +
 .../Gui/Component/SynchronizationWidget.cs         |   42 +---------
 Tests/Core/Store/TestProject.cs                    |   79 ++++++++++++++++++++
 5 files changed, 138 insertions(+), 41 deletions(-)
---
diff --git a/LongoMatch.Core/Store/Period.cs b/LongoMatch.Core/Store/Period.cs
index 3a4bed5..5c61e95 100644
--- a/LongoMatch.Core/Store/Period.cs
+++ b/LongoMatch.Core/Store/Period.cs
@@ -17,18 +17,18 @@
 //
 using System;
 using System.Linq;
-using System.Collections.Generic;
 using Newtonsoft.Json;
 
 namespace LongoMatch.Core.Store
 {
+       [Serializable]
        public class Period: Timer
        {
 
                public Period ()
                {
                }
-               
+
                [JsonIgnore]
                public TimeNode PeriodNode {
                        get {
@@ -39,8 +39,9 @@ namespace LongoMatch.Core.Store
                                if (stop.MSeconds == 0) {
                                        stop = null;
                                }
-                               return new TimeNode {Name=Name,
-                                       Start = start, Stop = stop};
+                               return new TimeNode {Name = Name,
+                                       Start = start, Stop = stop
+                               };
                        }
                        set {
                                foreach (TimeNode tn in Nodes) {
diff --git a/LongoMatch.Core/Store/Project.cs b/LongoMatch.Core/Store/Project.cs
index f6a849f..2a8f278 100644
--- a/LongoMatch.Core/Store/Project.cs
+++ b/LongoMatch.Core/Store/Project.cs
@@ -497,6 +497,54 @@ namespace LongoMatch.Core.Store
                        Description.VisitorGoals = GetScore (TeamType.VISITOR);
                }
 
+
+               /// <summary>
+               /// Resynchronize events with the periods synced with the video file.
+               /// Imported projects or fake analysis projects create events assuming periods
+               /// don't have gaps between them.
+               /// After adding a file to the project and synchronizing the periods with the
+               /// video file, all events must be offseted with the new start time of the period.
+               /// 
+               /// Before sync:
+               ///   Period 1: start=00:00:00 Period 2: start=00:30:00
+               ///   evt1 00:10:00            evt2 00:32:00
+               /// After sync:
+               ///   Period 1: start=00:05:00 Period 2: start= 00:39:00
+               ///   evt1 00:15:00            evt2 00:41:00
+               /// </summary>
+               /// <param name="periods">The new periods syncrhonized with the video file.</param>
+               public void ResyncEvents (List<Period> periods)
+               {
+                       List<TimelineEvent> newTimeline = new List<TimelineEvent> ();
+
+                       if (periods.Count != Periods.Count) {
+                               throw new IndexOutOfRangeException (
+                                       "Periods count is different from the project's ones");
+                       }
+
+                       for (int i = 0; i < periods.Count; i++) {
+                               Period oldPeriod = Periods [i];
+                               TimeNode oldTN = oldPeriod.PeriodNode;
+                               TimeNode newTN = periods [i].PeriodNode;
+                               Time diff = newTN.Start - oldTN.Start;
+
+                               /* Find the events in this period */
+                               var periodEvents = Timeline.Where (e =>
+                                       e.EventTime >= oldTN.Start &&
+                                                  e.EventTime <= oldTN.Stop).ToList ();
+
+                               /* Apply new offset and move the new timeline so that the next
+                                * iteration for the following period does not use them anymore */
+                               periodEvents.ForEach (e => {
+                                       e.Move (diff);
+                                       newTimeline.Add (e);
+                                       Timeline.Remove (e);
+                               });
+                               oldPeriod.Nodes.ForEach (t => t.Move (diff));
+                       }
+                       Timeline = newTimeline;
+               }
+
                public bool Equals (Project project)
                {
                        if (project == null)
diff --git a/LongoMatch.Drawing/CanvasObjects/Dashboard/TimerObject.cs 
b/LongoMatch.Drawing/CanvasObjects/Dashboard/TimerObject.cs
index 0120802..d1cdc55 100644
--- a/LongoMatch.Drawing/CanvasObjects/Dashboard/TimerObject.cs
+++ b/LongoMatch.Drawing/CanvasObjects/Dashboard/TimerObject.cs
@@ -18,6 +18,7 @@
 using LongoMatch.Core.Common;
 using LongoMatch.Core.Interfaces.Drawing;
 using LongoMatch.Core.Store;
+using System.IO;
 
 namespace LongoMatch.Drawing.CanvasObjects.Dashboard
 {
diff --git a/LongoMatch.GUI/Gui/Component/SynchronizationWidget.cs 
b/LongoMatch.GUI/Gui/Component/SynchronizationWidget.cs
index a044cde..ca09325 100644
--- a/LongoMatch.GUI/Gui/Component/SynchronizationWidget.cs
+++ b/LongoMatch.GUI/Gui/Component/SynchronizationWidget.cs
@@ -39,7 +39,7 @@ namespace LongoMatch.Gui.Component
                Time duration;
                Project project;
                PeriodsMenu menu;
-               Dictionary<Period, Period> periodsDict;
+               List<Period> periods;
                double maxSecondsPerPixels;
 
                enum DidacticMessage
@@ -179,39 +179,13 @@ namespace LongoMatch.Gui.Component
 
                        if (!resyncEvents)
                                return;
-
-                       /* Resynchronize events with the new start times of the period they belong too.
-                        * Imported projects or fake analysis projects create events assuming periods
-                        * don't have gaps between them.
-                        * After adding a file to the project and synchronizing the periods with the
-                        * video file, all events must be offseted with the new start time of the period.
-                        * 
-                        * Before sync:
-                        *   Period 1: start=00:00:00 Period 2: start=00:30:00
-                        *   evt1 00:10:00            evt2 00:32:00
-                        * After sync:
-                        *   Period 1: start=00:05:00 Period 2: start= 00:39:00
-                        *   evt1 00:15:00            evt2 00:41:00
-                        */
-                       foreach (Period p in periodsDict.Keys) {
-                               Period newp = periodsDict [p];
-                               TimeNode tn = p.PeriodNode;
-                               Time diff = newp.PeriodNode.Start - tn.Start;
-                               foreach (TimelineEvent evt in project.Timeline.Where
-                                        (e=>e.EventTime > tn.Start && e.EventTime < tn.Stop)) {
-                                       evt.Move (diff);
-                               }
-                               foreach (TimeNode t in p.Nodes) {
-                                       t.Move (diff);
-                               }
-                       }
+                       project.ResyncEvents (periods);
                }
 
                public Project Project {
                        set {
                                Time start, pDuration;
                                List<string> gamePeriods;
-                               List<Period> periods;
                                MediaFile file;
 
                                this.project = value;
@@ -223,7 +197,6 @@ namespace LongoMatch.Gui.Component
                                file = fileSet.FirstOrDefault ();
                                duration = file.Duration;
                                pDuration = new Time (duration.MSeconds / gamePeriods.Count);
-                               periodsDict = new Dictionary <Period, Period> ();
                                if (project.Periods == null || project.Periods.Count == 0) {
                                        /* If no periods are provided create the default ones
                                         * defined in the dashboard */
@@ -238,14 +211,9 @@ namespace LongoMatch.Gui.Component
                                        }
                                        value.Periods = periods;
                                } else {
-                                       /* Create a copy of the original periods and a mapping
-                                        * to resynchronize the events in SaveChanges() */
-                                       foreach (Period p in project.Periods) {
-                                               Period newp = new Period { Name = p.Name };
-                                               newp.Nodes.Add (p.PeriodNode);
-                                               periodsDict.Add (p, newp);
-                                       }
-                                       periods = periodsDict.Values.ToList ();
+                                       /* Create a copy of the project periods and keep the
+                                        * project ones to resynchronize the events in SaveChanges() */
+                                       periods = project.Periods.Clone ();
                                }
 
                                camerasLabels.Load (fileSet);
diff --git a/Tests/Core/Store/TestProject.cs b/Tests/Core/Store/TestProject.cs
index 197e23b..8aa3685 100644
--- a/Tests/Core/Store/TestProject.cs
+++ b/Tests/Core/Store/TestProject.cs
@@ -269,5 +269,84 @@ namespace Tests.Core.Store
                public void TestImport ()
                {
                }
+
+               [Test ()]
+               public void TestResyncEvents ()
+               {
+                       Project p = CreateProject (false);
+                       int offset1 = 100, offset2 = 120, offset3 = 150;
+                       Period period;
+                       List<Period> syncedPeriods;
+
+                       period = new Period ();
+                       period.Nodes.Add (new TimeNode { Start = new Time (0),
+                               Stop = new Time (3000)
+                       });
+                       p.Periods.Add (period);
+                       period = new Period ();
+                       period.Nodes.Add (new TimeNode { Start = new Time (3001),
+                               Stop = new Time (6000)
+                       });
+                       p.Periods.Add (period);
+                       period = new Period ();
+                       period.Nodes.Add (new TimeNode { Start = new Time (6001),
+                               Stop = new Time (6500)
+                       });
+                       p.Periods.Add (period);
+
+                       /* Test with a list of periods that don't match */
+                       Assert.Throws<IndexOutOfRangeException> (
+                               delegate {
+                                       p.ResyncEvents (new List<Period> ());
+                               });
+
+                       syncedPeriods = new List<Period> ();
+                       period = new Period ();
+                       period.Nodes.Add (new TimeNode {
+                               Start = new Time (0 + offset1),
+                               Stop = new Time (3000 + offset1)
+                       });
+                       syncedPeriods.Add (period);
+                       period = new Period ();
+                       period.Nodes.Add (new TimeNode {
+                               Start = new Time (3001 + offset2),
+                               Stop = new Time (6000 + offset2)
+                       });
+                       syncedPeriods.Add (period);
+                       period = new Period ();
+                       period.Nodes.Add (new TimeNode {
+                               Start = new Time (6001 + offset3),
+                               Stop = new Time (6500 + offset3)
+                       });
+                       syncedPeriods.Add (period);
+
+                       /* 1st Period */
+                       p.Timeline.Add (new TimelineEvent { EventTime = new Time (0) });
+                       p.Timeline.Add (new TimelineEvent { EventTime = new Time (1500) });
+                       p.Timeline.Add (new TimelineEvent { EventTime = new Time (3000) });
+                       /* 2nd Period */
+                       p.Timeline.Add (new TimelineEvent { EventTime = new Time (3001) });
+                       p.Timeline.Add (new TimelineEvent { EventTime = new Time (4500) });
+                       p.Timeline.Add (new TimelineEvent { EventTime = new Time (6000) });
+                       /* 3nd Period */
+                       p.Timeline.Add (new TimelineEvent { EventTime = new Time (6001) });
+                       p.Timeline.Add (new TimelineEvent { EventTime = new Time (6200) });
+                       p.Timeline.Add (new TimelineEvent { EventTime = new Time (6500) });
+
+                       List<TimelineEvent> oldTimeline = p.Timeline.Clone ();
+
+                       p.ResyncEvents (syncedPeriods);
+                       Assert.AreEqual (oldTimeline [0].EventTime + offset1, p.Timeline [0].EventTime);
+                       Assert.AreEqual (oldTimeline [1].EventTime + offset1, p.Timeline [1].EventTime);
+                       Assert.AreEqual (oldTimeline [2].EventTime + offset1, p.Timeline [2].EventTime);
+
+                       Assert.AreEqual (oldTimeline [3].EventTime + offset2, p.Timeline [3].EventTime);
+                       Assert.AreEqual (oldTimeline [4].EventTime + offset2, p.Timeline [4].EventTime);
+                       Assert.AreEqual (oldTimeline [5].EventTime + offset2, p.Timeline [5].EventTime);
+
+                       Assert.AreEqual (oldTimeline [6].EventTime + offset3, p.Timeline [6].EventTime);
+                       Assert.AreEqual (oldTimeline [7].EventTime + offset3, p.Timeline [7].EventTime);
+                       Assert.AreEqual (oldTimeline [8].EventTime + offset3, p.Timeline [8].EventTime);
+               }
        }
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]