Calculate timeslot overlaps or lack thereof
authorGeorgios Gousios <gousiosg@gmail.com>
Fri, 2 Dec 2011 14:11:36 +0000 (16:11 +0200)
committerGeorgios Gousios <gousiosg@gmail.com>
Fri, 2 Dec 2011 14:11:36 +0000 (16:11 +0200)
logic/src/main/scala/gr/grnet/aquarium/logic/accounting/dsl/Timeslot.scala
logic/src/test/scala/gr/grnet/aquarium/logic/test/DSLUtilsTest.scala
logic/src/test/scala/gr/grnet/aquarium/logic/test/PerfTest.scala
logic/src/test/scala/gr/grnet/aquarium/logic/test/TimeslotTest.scala [new file with mode: 0644]

index 545950f..420bc79 100644 (file)
@@ -36,6 +36,7 @@
 package gr.grnet.aquarium.logic.accounting.dsl
 
 import java.util.Date
+import scala.collection.mutable
 
 /**
  * A representation of a timeslot with a start and end date.
@@ -49,18 +50,18 @@ case class Timeslot(from: Date, to: Date) {
   assert(to != null)
   assert(from.before(to))
 
+  def startsBefore(t: Timeslot) : Boolean = this.from.before(t.from)
+
+  def startsAfter(t: Timeslot) : Boolean = this.from.after(t.from)
+
+  def endsBefore(t: Timeslot) : Boolean = this.to.before(t.to)
+
+  def endsAfter(t: Timeslot) : Boolean = this.to.after(t.to)
+
   /**
    * Check whether this time slot fully contains the provided one.
    */
-  def contains(t: Timeslot) : Boolean = {
-    if (this.from.after(t.from))
-      return false
-
-    if (this.to.before(t.to))
-      return false
-
-    true
-  }
+  def contains(t: Timeslot) : Boolean = t.startsAfter(this) && t.endsBefore(this)
 
   /**
    * Check whether this timeslot contains the provided time instant.
@@ -98,4 +99,74 @@ case class Timeslot(from: Date, to: Date) {
       else
         List(t, this)
   }
+
+  /**
+   * Split the timeslot in two parts at the provided timestamp, if the
+   * timestamp falls within the timeslot boundaries.
+   */
+  def slice(d: Date) : List[Timeslot] =
+    if (includes(d))
+      List(Timeslot(from, d), Timeslot(d,to))
+    else
+      List(this)
+
+  /**
+   * Find and return the timeslots whithin which this Timeslot overrides
+   * with the provided list of timeslots. For example if:
+   * 
+   *  - `this == Timeslot(7,20)`
+   *  - `list == List(Timeslot(1,3), Timeslot(6,8), Timeslot(11,15))`
+   *
+   * the result will be: `List(Timeslot(7,8), Timeslot(11,15))`
+   */
+  def overlappingTimeslots(list: List[Timeslot]) : List[Timeslot] = {
+
+    val result = new mutable.ListBuffer[Timeslot]()
+
+    list.foreach {
+      t =>
+        if (t.contains(this) || this.contains(t)) result += t
+        else if (t.overlaps(this) && t.startsBefore(this)) result += this.slice(t.to).head
+        else if (t.overlaps(this) && t.startsAfter(this)) result += this.slice(t.from).tail.head
+    }
+    result.toList
+  }
+
+  /**
+   * Find and return the timeslots whithin which this Timeslot does not
+   * override with the provided list of timeslots. For example if:
+   *
+   *  - `this == Timeslot(7,20)`
+   *  - `list == List(Timeslot(1,3), Timeslot(6,8), Timeslot(11,15))`
+   *
+   * the result will be: `List(Timeslot(9,10), Timeslot(15,20))`
+   */
+  def nonOverlappingTimeslots(list: List[Timeslot]): List[Timeslot] = {
+
+    def build(acc: List[Timeslot], listPart: List[Timeslot]): List[Timeslot] = {
+      list match {
+        case Nil => acc
+        case x :: Nil => computeGap1(x, this)
+        case x :: y :: rest =>
+          val gap = computeGap2(x, y, this)
+          build(acc ++ gap, y :: rest)
+      }
+    }
+
+    def computeGap1(x: Timeslot, to: Timeslot) : List[Timeslot] =
+      if (x.startsBefore(to) && x.endsBefore(to))
+        List(Timeslot(to.from, x.from))
+      else if (x.startsBefore(to) && x.endsAfter(to))
+        List()
+      else if (x.startsAfter(to) && x.endsAfter(to))
+        List(Timeslot(to.from, x.from))
+      else if (x.startsAfter(to) && x.endsBefore(to))
+        List(Timeslot(to.from, x.from), Timeslot(to.to, x.to))
+      else
+        List()
+
+    def computeGap2(x: Timeslot, y: Timeslot, to: Timeslot) : List[Timeslot] = List()
+
+    build(Nil, list)
+  }
 }
\ No newline at end of file
index 81199b5..e158ed9 100644 (file)
@@ -204,7 +204,6 @@ class DSLUtilsTest extends DSLTestBase with DSLUtils with TestMethods {
   @Test
   def testFindEffective = {
     before
-
     val agr = creditpolicy.findAgreement("scaledbandwidth").get
 
     val ts1 = 1322649482000L //Wed, 30 Nov 2011 10:38:02 GMT
index 7841b76..3522742 100644 (file)
@@ -37,7 +37,7 @@ package gr.grnet.aquarium.logic.test
 
 import org.junit.Test
 import gr.grnet.aquarium.logic.accounting.dsl.{DSLTimeFrame, DSLTimeFrameRepeat, DSL, DSLUtils}
-import java.util.{Date, GregorianCalendar, Calendar}
+import java.util.{Date}
 import org.junit.Assume._
 import gr.grnet.aquarium.LogicTestsAssumptions
 
diff --git a/logic/src/test/scala/gr/grnet/aquarium/logic/test/TimeslotTest.scala b/logic/src/test/scala/gr/grnet/aquarium/logic/test/TimeslotTest.scala
new file mode 100644 (file)
index 0000000..0b6ddc6
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2011 GRNET S.A. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials
+ *      provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and
+ * documentation are those of the authors and should not be
+ * interpreted as representing official policies, either expressed
+ * or implied, of GRNET S.A.
+ */
+
+package gr.grnet.aquarium.logic.test
+
+import gr.grnet.aquarium.util.TestMethods
+import org.junit.Assert._
+import org.junit.{Test}
+import gr.grnet.aquarium.logic.accounting.dsl.Timeslot
+import java.util.Date
+
+/**
+ * Tests for the Timeslot class
+ *
+ * @author Georgios Gousios <gousiosg@gmail.com>
+ */
+class TimeslotTest extends TestMethods {
+
+  @Test
+  def testOverlappingTimeslots = {
+    var t = Timeslot(new Date(7), new Date(20))
+    val list = List(Timeslot(new Date(1), new Date(3)),
+      Timeslot(new Date(6), new Date(8)),
+      Timeslot(new Date(11), new Date(15)))
+
+    var result = t.overlappingTimeslots(list)
+    assertEquals(2, result.size)
+    assertEquals(Timeslot(new Date(7), new Date(8)), result.head)
+    assertEquals(Timeslot(new Date(11), new Date(15)), result.tail.head)
+
+    t = Timeslot(new Date(9), new Date(10))
+    result = t.overlappingTimeslots(list)
+    assertEquals(0, result.size)
+  }
+
+  @Test
+  def testNonOverlappingTimeslots = {
+    var t = Timeslot(new Date(7), new Date(20))
+    val list = List(Timeslot(new Date(1), new Date(3)),
+      Timeslot(new Date(6), new Date(8)),
+      Timeslot(new Date(11), new Date(15)))
+
+    //var result = t.nonOverlappingTimeslots(list)
+    
+  }
+}
\ No newline at end of file