Change the representation of computed credit values
[aquarium] / src / main / scala / gr / grnet / aquarium / charging / OnceChargingBehavior.scala
1 /*
2  * Copyright 2011-2012 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above
9  *      copyright notice, this list of conditions and the following
10  *      disclaimer.
11  *
12  *   2. Redistributions in binary form must reproduce the above
13  *      copyright notice, this list of conditions and the following
14  *      disclaimer in the documentation and/or other materials
15  *      provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  * The views and conclusions contained in the software and
31  * documentation are those of the authors and should not be
32  * interpreted as representing official policies, either expressed
33  * or implied, of GRNET S.A.
34  */
35
36 package gr.grnet.aquarium.charging
37
38 import gr.grnet.aquarium.{Real, Aquarium}
39 import gr.grnet.aquarium.charging.state.UserAgreementHistoryModel
40 import gr.grnet.aquarium.computation.BillingMonthInfo
41 import gr.grnet.aquarium.event.DetailsModel
42 import gr.grnet.aquarium.message.avro.gen.{UserStateMsg, WalletEntryMsg, ResourcesChargingStateMsg, ResourceTypeMsg, ResourceInstanceChargingStateMsg, ResourceEventMsg}
43 import gr.grnet.aquarium.message.MessageConstants
44
45 /**
46  * A charging behavior for which resource events just carry a credit amount that will be added to the total one.
47  *
48  * Examples are: a) Give a gift of X credits to the user, b) User bought a book, so charge for the book price.
49  *
50  * @author Christos KK Loverdos <loverdos@gmail.com>
51  */
52 final class OnceChargingBehavior extends ChargingBehaviorSkeleton(Nil) {
53   def computeCreditsToSubtract(
54       resourceInstanceChargingState: ResourceInstanceChargingStateMsg,
55       oldCredits: Real,
56       timeDeltaMillis: Long,
57       unitPrice: Real
58   ): (Real, String /* explanation */) = {
59
60     val currentValue = Real(resourceInstanceChargingState.getCurrentValue)
61     // Always remember to multiply with the `unitPrice`, since it scales the credits, depending on
62     // the particular resource type tha applies.
63     val credits = currentValue * unitPrice
64     val explanation = "Value(%s) * UnitPrice(%s)".format(currentValue, unitPrice)
65
66     (credits, explanation)
67   }
68
69   def computeSelectorPath(
70       chargingBehaviorDetails: DetailsModel.Type,
71       resourceInstanceChargingState: ResourceInstanceChargingStateMsg,
72       currentResourceEvent: ResourceEventMsg,
73       referenceFromMillis: Long,
74       referenceToMillis: Long,
75       totalCredits: Real
76   ): List[String] = {
77     List(MessageConstants.DefaultSelectorKey)
78   }
79
80   override def processResourceEvent(
81       aquarium: Aquarium,
82       resourceEvent: ResourceEventMsg,
83       resourceType: ResourceTypeMsg,
84       billingMonthInfo: BillingMonthInfo,
85       resourcesChargingState: ResourcesChargingStateMsg,
86       userAgreementHistoryModel: UserAgreementHistoryModel,
87       userStateMsg: UserStateMsg,
88       walletEntryRecorder: WalletEntryMsg ⇒ Unit
89   ): (Int, Real) = {
90     // The credits are given in the value
91     // But we cannot just apply them, since we also need to take into account the unit price.
92     // Normally, the unit price is 1.0 but we have the flexibility to allow more stuff).
93
94     // 1. Ensure proper initial state per resource and per instance
95     ensureInitializedWorkingState(resourcesChargingState,resourceEvent)
96
97     // 2. Fill in data from the new event
98     val stateOfResourceInstance = resourcesChargingState.getStateOfResourceInstance
99     val resourcesChargingStateDetails = resourcesChargingState.getDetails
100     val instanceID = resourceEvent.getInstanceID
101     val resourceInstanceChargingState = stateOfResourceInstance.get(instanceID)
102     fillWorkingResourceInstanceChargingStateFromEvent(resourceInstanceChargingState, resourceEvent)
103
104     computeWalletEntriesForNewEvent(
105       resourceEvent,
106       resourceType,
107       billingMonthInfo,
108       Real(userStateMsg.getTotalCredits),
109       resourceEvent.getOccurredMillis,
110       resourceEvent.getOccurredMillis + 1, // single point in time
111       userAgreementHistoryModel.agreementByTimeslot,
112       resourcesChargingStateDetails,
113       resourceInstanceChargingState,
114       aquarium,
115       walletEntryRecorder
116     )
117   }
118
119   def initialChargingDetails = {
120     DetailsModel.make
121   }
122
123   def computeNewAccumulatingAmount(
124       resourceInstanceChargingState: ResourceInstanceChargingStateMsg,
125       eventDetails: DetailsModel.Type
126   ): Real = {
127     Real(resourceInstanceChargingState.getOldAccumulatingAmount)
128   }
129
130   def createVirtualEventsForRealtimeComputation(
131       userID: String,
132       resourceTypeName: String,
133       resourceInstanceID: String,
134       eventOccurredMillis: Long,
135       resourceInstanceChargingState: ResourceInstanceChargingStateMsg
136   ): List[ResourceEventMsg] = {
137
138     // We optimize and generate no virtual event
139     Nil
140   }
141 }