Code + tests to merge overlapping timeslots
authorGeorgios Gousios <gousiosg@gmail.com>
Thu, 1 Dec 2011 15:13:27 +0000 (17:13 +0200)
committerGeorgios Gousios <gousiosg@gmail.com>
Thu, 1 Dec 2011 15:13:36 +0000 (17:13 +0200)
logic/src/main/scala/gr/grnet/aquarium/logic/accounting/dsl/DSLUtils.scala
logic/src/test/scala/gr/grnet/aquarium/logic/test/DSLUtilsTest.scala

index 4ab28f2..d181117 100644 (file)
@@ -131,15 +131,34 @@ trait DSLUtils extends DateUtils {
   }
 
   /**
+   * Merges overlapping timeslots. The merge is exhaustive only if the
+   * provided list is sorted in increasing timeslot from order.
+   */
+  def mergeOverlaps(list: List[Timeslot]): List[Timeslot] = {
+    list.foldLeft(List[Timeslot]()) {
+      (a, b) =>
+        if (a.isEmpty)
+          List(b)
+        else if (a.tail.isEmpty)
+          a.head.merge(b)
+        else {
+          val merged = a.tail.head.merge(b)
+          a ++ (if (merged.size == 1) merged else List(b))
+        }
+    }
+  }
+
+  /**
    * Get a list of all timeslots within which the provided time frame
    * is effective.
    */
   def allEffectiveTimeslots(spec: DSLTimeFrame):
   List[Timeslot] = {
 
-    spec.repeat.flatMap {
+    val l = spec.repeat.flatMap {
       r => effectiveTimeslots(r, spec.from, spec.to)
     } sortWith sorter
+    mergeOverlaps(l)
   }
 
   /**
@@ -149,9 +168,10 @@ trait DSLUtils extends DateUtils {
   def allEffectiveTimeslots(spec: DSLTimeFrame, from: Date, to: Date):
   List[Timeslot] = {
 
-    spec.repeat.flatMap {
+    val l = spec.repeat.flatMap {
       r => effectiveTimeslots(r, from, Some(to))
     } sortWith sorter
+    mergeOverlaps(l)
   }
 
   /**
index 752261a..81199b5 100644 (file)
@@ -90,6 +90,27 @@ class DSLUtilsTest extends DSLTestBase with DSLUtils with TestMethods {
   }
 
   @Test
+  def testMergeOverlaps = {
+    var l = List(Timeslot(new Date(12345000), new Date(13345000)),
+      Timeslot(new Date(12845000), new Date(13845000)))
+
+    var result = mergeOverlaps(l)
+    assertEquals(1, result.size)
+    assertEquals(Timeslot(new Date(12345000), new Date(13845000)), result.head)
+
+    l = l ++ List(Timeslot(new Date(13645000), new Date(14845000)))
+    result = mergeOverlaps(l)
+    assertEquals(1, result.size)
+    assertEquals(Timeslot(new Date(12345000), new Date(14845000)), result.head)
+
+    l = l ++ List(Timeslot(new Date(15845000), new Date(16845000)))
+    result = mergeOverlaps(l)
+    assertEquals(2, result.size)
+    assertEquals(Timeslot(new Date(12345000), new Date(14845000)), result.head)
+    assertEquals(Timeslot(new Date(15845000), new Date(16845000)), result.tail.head)
+  }
+
+  @Test
   def testEffectiveTimeslots = {
     val from =  new Date(1321621969000L) //Fri Nov 18 15:12:49 +0200 2011
     val to =  new Date(1324214719000L)   //Sun Dec 18 15:25:19 +0200 2011
@@ -214,7 +235,7 @@ class DSLUtilsTest extends DSLTestBase with DSLUtils with TestMethods {
     testSuccessiveTimeslots(result.tail)
   }
 
-  private def printTimeslots(result: List[(Date, Date)]) = {
-    result.foreach(p => print("from:%s to:%s\n".format(p._1, p._2)))
+  private def printTimeslots(result: List[Timeslot]) = {
+    result.foreach(p => print("from:%s to:%s\n".format(p.from, p.to)))
   }
 }
\ No newline at end of file