package gr.grnet.aquarium.computation
import collection.immutable.SortedMap
-import com.ckkloverdos.maybe.{NoVal, Maybe}
-import gr.grnet.aquarium.util.{ContextualLogger, Loggable}
-import gr.grnet.aquarium.AquariumInternalError
+import gr.grnet.aquarium.util.Loggable
import gr.grnet.aquarium.logic.accounting.dsl.Timeslot
import gr.grnet.aquarium.policy._
import collection.immutable
-import com.ckkloverdos.maybe.Just
-import gr.grnet.aquarium.policy.ResourceType
-import gr.grnet.aquarium.policy.EffectiveUnitPrice
-import gr.grnet.aquarium.charging.Chargeslot
+import gr.grnet.aquarium.policy.EffectiveUnitPriceModel
+import gr.grnet.aquarium.message.avro.gen.{EffectiveUnitPriceMsg, PolicyMsg, UserAgreementMsg, FullPriceTableMsg, EffectivePriceTableMsg, ChargeslotMsg}
/**
* Methods for converting accounting events to wallet entries.
* @param agreementTimeslots
* @return
*/
- protected
- def splitTimeslotByPoliciesAndAgreements(
+ private[this] def splitTimeslotByPoliciesAndAgreements(
referenceTimeslot: Timeslot,
policyTimeslots: List[Timeslot],
- agreementTimeslots: List[Timeslot],
- clogM: Maybe[ContextualLogger] = NoVal
+ agreementTimeslots: List[Timeslot]
): List[Timeslot] = {
// Align policy and agreement validity timeslots to the referenceTimeslot
* algorithm and price unit is in effect.
*
*/
- protected
- def resolveEffectiveUnitPrices(
+ private[this] def resolveEffectiveUnitPrices(
alignedTimeslot: Timeslot,
policy: PolicyModel,
agreement: UserAgreementModel,
- resourceType: ResourceType,
- clogOpt: Option[ContextualLogger] = None
- ): SortedMap[Timeslot, Double] = {
-
- val clog = ContextualLogger.fromOther(clogOpt, logger, "resolveEffectiveUnitPrices()")
+ fullPriceTableModelGetter: (UserAgreementModel, PolicyModel) ⇒ FullPriceTableModel,
+ effectivePriceTableModelSelector: FullPriceTableModel ⇒ EffectivePriceTableModel
+ ): SortedMap[Timeslot, String] = {
// Note that most of the code is taken from calcChangeChunks()
- val ret = resolveEffectiveUnitPricesForTimeslot(alignedTimeslot, policy, agreement, resourceType)
+ val ret = resolveEffectiveUnitPricesForTimeslot(
+ alignedTimeslot,
+ policy,
+ agreement,
+ fullPriceTableModelGetter,
+ effectivePriceTableModelSelector)
ret map {case (t,p) => (t,p.unitPrice)}
}
def computeInitialChargeslots(
referenceTimeslot: Timeslot,
- resourceType: ResourceType,
policyByTimeslot: SortedMap[Timeslot, PolicyModel],
agreementByTimeslot: SortedMap[Timeslot, UserAgreementModel],
- clogOpt: Option[ContextualLogger] = None
- ): List[Chargeslot] = {
-
- val clog = ContextualLogger.fromOther(clogOpt, logger, "computeInitialChargeslots()")
+ fullPriceTableModelGetter: (UserAgreementModel, PolicyModel) ⇒ FullPriceTableModel,
+ effectivePriceTableModelSelector: FullPriceTableModel ⇒ EffectivePriceTableModel
+ ): List[ChargeslotMsg] = {
val policyTimeslots = policyByTimeslot.keySet
val agreementTimeslots = agreementByTimeslot.keySet
}
// 1. Round ONE: split time according to overlapping policies and agreements.
- val alignedTimeslots = List(referenceTimeslot) //splitTimeslotByPoliciesAndAgreements(referenceTimeslot, policyTimeslots.toList, agreementTimeslots.toList, Just(clog))
+ //val alignedTimeslots = List(referenceTimeslot) //splitTimeslotByPoliciesAndAgreements(referenceTimeslot, policyTimeslots.toList, agreementTimeslots.toList, Just(clog))
+ val alignedTimeslots = splitTimeslotByPoliciesAndAgreements(referenceTimeslot, policyTimeslots.toList, agreementTimeslots.toList)
// 2. Round TWO: Use the aligned timeslots of Round ONE to produce even more
// fine-grained timeslots according to applicable algorithms.
val allChargeslots = for {
alignedTimeslot <- alignedTimeslots
} yield {
- val policy = policyByTimeslot.valuesIterator.next()//getPolicyWithin(alignedTimeslot)
+ //val policy = policyByTimeslot.valuesIterator.next()//getPolicyWithin(alignedTimeslot)
+ val policy = getPolicyWithin(alignedTimeslot)
// clog.debug("dslPolicy = %s", dslPolicy)
- val userAgreement = agreementByTimeslot.valuesIterator.next()//getAgreementWithin(alignedTimeslot)
+ //val userAgreement = agreementByTimeslot.valuesIterator.next()//getAgreementWithin(alignedTimeslot)
+ val userAgreement = getAgreementWithin(alignedTimeslot)
- // TODO: Factor this out, just like we did with:
- // TODO: val alignedTimeslots = splitTimeslotByPoliciesAndAgreements
- // Note that most of the code is already taken from calcChangeChunks()
- val unitPriceByTimeslot = resolveEffectiveUnitPrices(alignedTimeslot, policy, userAgreement, resourceType, Some(clog))
+ val unitPriceByTimeslot = resolveEffectiveUnitPrices(
+ alignedTimeslot,
+ policy,
+ userAgreement,
+ fullPriceTableModelGetter,
+ effectivePriceTableModelSelector
+ )
// Now, the timeslots must be the same
val finegrainedTimeslots = unitPriceByTimeslot.keySet
- val chargeslots = for (finegrainedTimeslot ← finegrainedTimeslots) yield {
- Chargeslot(
- finegrainedTimeslot.from.getTime,
- finegrainedTimeslot.to.getTime,
- unitPriceByTimeslot(finegrainedTimeslot)
- )
+ val chargeslots = for(finegrainedTimeslot ← finegrainedTimeslots) yield {
+ val cs = new ChargeslotMsg
+
+ cs.setStartMillis(finegrainedTimeslot.from.getTime)
+ cs.setStopMillis(finegrainedTimeslot.to.getTime)
+ cs.setUnitPrice(unitPriceByTimeslot(finegrainedTimeslot))
+
+ cs
}
chargeslots.toList
*
* result: List(Timeslot(a.from, b.to), Timeslot(b.to, a.to))
*/
- private[computation] def alignTimeslots(a: List[Timeslot],
- b: List[Timeslot]): List[Timeslot] = {
+ private[this] def alignTimeslots(
+ a: List[Timeslot],
+ b: List[Timeslot]
+ ): List[Timeslot] = {
def safeTail(foo: List[Timeslot]) = foo match {
case Nil => List()
if(a.isEmpty) return b
if(b.isEmpty) return a
-
+ if(a.head.from != b.head.from)
assert(a.head.from == b.head.from)
if(a.head.endsAfter(b.head)) {
}
}
- type PriceMap = immutable.SortedMap[Timeslot, EffectiveUnitPrice]
- private type PriceList = List[EffectiveUnitPrice]
- private def emptyMap = immutable.SortedMap[Timeslot,EffectiveUnitPrice]()
+ type PriceMap = immutable.SortedMap[Timeslot, EffectiveUnitPriceModel]
+ private type PriceList = List[EffectiveUnitPriceModel]
+ private def emptyMap = immutable.SortedMap[Timeslot,EffectiveUnitPriceModel]()
/**
* Resolves the effective price list for each chunk of the
* provided timeslot and returns it as a Map
*/
- private def resolveEffectiveUnitPricesForTimeslot(
- alignedTimeslot: Timeslot,
- policy: PolicyModel,
- agreement: UserAgreementModel,
- resourceType: ResourceType
- ): PriceMap = {
-
- val role = agreement.role
- val fullPriceTable = agreement.fullPriceTableRef match {
- case PolicyDefinedFullPriceTableRef ⇒
- policy.roleMapping.get(role) match {
- case Some(fullPriceTable) ⇒
- fullPriceTable
-
- case None ⇒
- throw new AquariumInternalError("Unknown role %s".format(role))
- }
-
- case AdHocFullPriceTableRef(fullPriceTable) ⇒
- fullPriceTable
- }
-
- val effectivePriceTable = fullPriceTable.perResource.get(resourceType.name) match {
- case None ⇒
- throw new AquariumInternalError("Unknown resource type %s".format(role))
-
- case Some(effectivePriceTable) ⇒
- effectivePriceTable
- }
-
- //resolveEffective(alignedTimeslot, effectivePriceTable.priceOverrides)
- immutable.SortedMap(alignedTimeslot -> effectivePriceTable.priceOverrides.head)
+ private[this] def resolveEffectiveUnitPricesForTimeslot(
+ alignedTimeslot: Timeslot,
+ policy: PolicyModel,
+ userAgreement: UserAgreementModel,
+ fullPriceTableModelGetter: (UserAgreementModel, PolicyModel) ⇒ FullPriceTableModel,
+ effectivePriceTableModelSelector: FullPriceTableModel ⇒ EffectivePriceTableModel
+ ): PriceMap = {
+
+ val fullPriceTable = fullPriceTableModelGetter(userAgreement, policy)
+ val effectivePriceTable = effectivePriceTableModelSelector(fullPriceTable)
+
+ resolveEffective(alignedTimeslot, effectivePriceTable.priceOverrides)
+ //immutable.SortedMap(alignedTimeslot -> effectivePriceTable.priceOverrides.head)
}
- private def printPriceList(p: PriceList) : Unit = {
+ private[this] def printPriceList(p: PriceList) : Unit = {
Console.err.println("BEGIN PRICE LIST")
for { p1 <- p } Console.err.println(p1)
Console.err.println("END PRICE LIST")
}
- private def printPriceMap(m: PriceMap) = {
+ private[this] def printPriceMap(m: PriceMap) = {
Console.err.println("BEGIN PRICE MAP")
for { (t,p) <- m.toList } Console.err.println("Timeslot " + t + "\t\t" + p)
Console.err.println("END PRICE MAP")
}
- private def resolveEffective(alignedTimeslot: Timeslot,p:PriceList): PriceMap = {
- Console.err.println("\n\nInput timeslot: " + alignedTimeslot + "\n\n")
- printPriceList(p)
+ private[this] def resolveEffective(alignedTimeslot: Timeslot,p:PriceList): PriceMap = {
+ //Console.err.println("\n\nInput timeslot: " + alignedTimeslot + "\n\n")
+ //printPriceList(p)
val ret = resolveEffective3(alignedTimeslot,p) //HERE
- printPriceMap(ret)
+ //printPriceMap(ret)
ret
}
- private def resolveEffective3(alignedTimeslot: Timeslot, effectiveUnitPrices: PriceList): PriceMap =
+ private[this] def resolveEffective3(alignedTimeslot: Timeslot, effectiveUnitPrices: PriceList): PriceMap =
effectiveUnitPrices match {
case Nil =>
emptyMap