volume discount integrated in turbo system :)

This commit is contained in:
Radu Ioan Fericean
2012-02-27 14:51:04 +02:00
parent 1c5626b9f7
commit 79a264b974
8 changed files with 109 additions and 59 deletions

View File

@@ -55,7 +55,8 @@ type CallDescriptor struct {
TimeStart, TimeEnd time.Time
Amount float64
ActivationPeriods []*ActivationPeriod
StorageGetter StorageGetter
storageGetter StorageGetter
userBudget *UserBudget
}
/*
@@ -67,6 +68,23 @@ func (cd *CallDescriptor) AddActivationPeriod(aps ...*ActivationPeriod) {
}
}
/*
Gets and caches the user budget information.
*/
func (cd *CallDescriptor) getUserBudget() (ub *UserBudget, err error) {
if cd.userBudget == nil {
cd.userBudget, err = cd.storageGetter.GetUserBudget(cd.Subject)
}
return cd.userBudget, err
}
/*
Exported method to set the storage getter.
*/
func (cd *CallDescriptor) SetStorageGetter(sg StorageGetter) {
cd.storageGetter = sg
}
/*
Restores the activation periods from storage.
*/
@@ -75,10 +93,10 @@ func (cd *CallDescriptor) RestoreFromStorage() (destPrefix string, err error) {
base := fmt.Sprintf("%s:%s:", cd.CstmId, cd.Subject)
destPrefix = cd.DestinationPrefix
key := base + destPrefix
values, err := cd.StorageGetter.GetActivationPeriods(key)
values, err := cd.storageGetter.GetActivationPeriods(key)
//get for a smaller prefix if the orignal one was not found
for i := len(cd.DestinationPrefix); err != nil && i >= MinPrefixLength; values, err = cd.StorageGetter.GetActivationPeriods(key) {
for i := len(cd.DestinationPrefix); err != nil && i >= MinPrefixLength; values, err = cd.storageGetter.GetActivationPeriods(key) {
i--
destPrefix = cd.DestinationPrefix[:i]
key = base + destPrefix
@@ -111,9 +129,9 @@ Splits the received timespan into sub time spans according to the activation per
func (cd *CallDescriptor) splitTimeSpan(firstSpan *TimeSpan) (timespans []*TimeSpan) {
timespans = append(timespans, firstSpan)
// split on (free) minute buckets
if userBudget, err := cd.StorageGetter.GetUserBudget(cd.Subject); err == nil && userBudget != nil {
if userBudget, err := cd.getUserBudget(); err == nil && userBudget != nil {
userBudget.mux.RLock()
_, bucketList := userBudget.getSecondsForPrefix(cd.StorageGetter, cd.DestinationPrefix)
_, bucketList := userBudget.getSecondsForPrefix(cd.storageGetter, cd.DestinationPrefix)
for _, mb := range bucketList {
for i := 0; i < len(timespans); i++ {
if timespans[i].MinuteInfo != nil {
@@ -192,7 +210,7 @@ func (cd *CallDescriptor) GetCost() (*CallCost, error) {
if ts.MinuteInfo == nil && i == 0 {
connectionFee = ts.Interval.ConnectFee
}
cost += ts.GetCost()
cost += ts.GetCost(cd)
}
cc := &CallCost{TOR: cd.TOR,
CstmId: cd.CstmId,
@@ -216,7 +234,7 @@ func (cd *CallDescriptor) getPresentSecondCost() (cost float64, err error) {
timespans := cd.splitTimeSpan(ts)
if len(timespans) > 0 {
cost = round(timespans[0].GetCost(), 3)
cost = round(timespans[0].GetCost(cd), 3)
}
return
}
@@ -230,10 +248,10 @@ func (cd *CallDescriptor) GetMaxSessionTime() (seconds float64, err error) {
_, err = cd.RestoreFromStorage()
now := time.Now()
availableCredit, availableSeconds := 0.0, 0.0
if userBudget, err := cd.StorageGetter.GetUserBudget(cd.Subject); err == nil && userBudget != nil {
if userBudget, err := cd.getUserBudget(); err == nil && userBudget != nil {
userBudget.mux.RLock()
availableCredit = userBudget.Credit
availableSeconds, _ = userBudget.getSecondsForPrefix(cd.StorageGetter, cd.DestinationPrefix)
availableSeconds, _ = userBudget.getSecondsForPrefix(cd.storageGetter, cd.DestinationPrefix)
userBudget.mux.RUnlock()
} else {
return cd.Amount, err
@@ -254,7 +272,7 @@ func (cd *CallDescriptor) GetMaxSessionTime() (seconds float64, err error) {
if ts.MinuteInfo == nil && i == 0 {
cost += ts.Interval.ConnectFee
}
cost += ts.GetCost()
cost += ts.GetCost(cd)
}
if cost < availableCredit {
return maxSessionSeconds, nil
@@ -266,22 +284,22 @@ func (cd *CallDescriptor) GetMaxSessionTime() (seconds float64, err error) {
}
func (cd *CallDescriptor) DebitCents() (left float64, err error) {
if userBudget, err := cd.StorageGetter.GetUserBudget(cd.Subject); err == nil && userBudget != nil {
return userBudget.debitMoneyBudget(cd.StorageGetter, cd.Amount), nil
if userBudget, err := cd.getUserBudget(); err == nil && userBudget != nil {
return userBudget.debitMoneyBudget(cd.storageGetter, cd.Amount), nil
}
return 0.0, err
}
func (cd *CallDescriptor) DebitSMS() (left float64, err error) {
if userBudget, err := cd.StorageGetter.GetUserBudget(cd.Subject); err == nil && userBudget != nil {
return userBudget.debitSMSBuget(cd.StorageGetter, cd.Amount)
if userBudget, err := cd.getUserBudget(); err == nil && userBudget != nil {
return userBudget.debitSMSBuget(cd.storageGetter, cd.Amount)
}
return 0, err
}
func (cd *CallDescriptor) DebitSeconds() (err error) {
if userBudget, err := cd.StorageGetter.GetUserBudget(cd.Subject); err == nil && userBudget != nil {
return userBudget.debitMinutesBudget(cd.StorageGetter, cd.Amount, cd.DestinationPrefix)
if userBudget, err := cd.getUserBudget(); err == nil && userBudget != nil {
return userBudget.debitMinutesBudget(cd.storageGetter, cd.Amount, cd.DestinationPrefix)
}
return err
}

View File

@@ -29,7 +29,7 @@ func TestKyotoSplitSpans(t *testing.T) {
t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
cd.RestoreFromStorage()
timespans := cd.splitInTimeSpans()
@@ -44,7 +44,7 @@ func TestRedisSplitSpans(t *testing.T) {
t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0257", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0257", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
cd.RestoreFromStorage()
timespans := cd.splitInTimeSpans()
@@ -60,13 +60,13 @@ func TestKyotoGetCost(t *testing.T) {
t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
result, _ := cd.GetCost()
expected := &CallCost{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", Cost: 540, ConnectFee: 0}
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
t.Errorf("Expected %v was %v", expected, result)
}
cd = &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0257", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd = &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0257", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
result, _ = cd.GetCost()
expected = &CallCost{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0257", Cost: 540, ConnectFee: 0}
}
@@ -77,7 +77,7 @@ func TestRedisGetCost(t *testing.T) {
t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
result, _ := cd.GetCost()
expected := &CallCost{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", Cost: 540, ConnectFee: 0}
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
@@ -94,7 +94,7 @@ func TestMongoGetCost(t *testing.T) {
t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
result, _ := cd.GetCost()
expected := &CallCost{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", Cost: 540, ConnectFee: 0}
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
@@ -108,7 +108,7 @@ func TestFullDestNotFound(t *testing.T) {
t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256308200", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256308200", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
result, _ := cd.GetCost()
expected := &CallCost{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", Cost: 540, ConnectFee: 0}
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
@@ -122,7 +122,7 @@ func TestMultipleActivationPeriods(t *testing.T) {
t1 := time.Date(2012, time.February, 8, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 8, 18, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0257308200", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0257308200", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
result, _ := cd.GetCost()
expected := &CallCost{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0257", Cost: 330, ConnectFee: 0}
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
@@ -138,7 +138,7 @@ func TestSpansMultipleActivationPeriods(t *testing.T) {
t1 := time.Date(2012, time.February, 7, 23, 50, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 8, 0, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0257308200", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0257308200", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
result, _ := cd.GetCost()
expected := &CallCost{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0257", Cost: 360, ConnectFee: 0}
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
@@ -152,7 +152,7 @@ func TestLessThanAMinute(t *testing.T) {
t1 := time.Date(2012, time.February, 8, 23, 50, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 8, 23, 50, 30, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0257308200", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0257308200", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
result, _ := cd.GetCost()
expected := &CallCost{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0257", Cost: 0.5, ConnectFee: 0}
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
@@ -166,7 +166,7 @@ func TestUniquePrice(t *testing.T) {
t1 := time.Date(2012, time.February, 8, 22, 50, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 8, 23, 50, 21, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0723045326", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0723045326", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
result, _ := cd.GetCost()
expected := &CallCost{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0723", Cost: 60.35, ConnectFee: 0}
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
@@ -180,7 +180,7 @@ func TestPresentSecodCost(t *testing.T) {
t1 := time.Date(2012, time.February, 8, 22, 50, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 8, 23, 50, 21, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0723", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0723", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
result, _ := cd.getPresentSecondCost()
expected := 0.016
if result != expected {
@@ -194,7 +194,7 @@ func TestMinutesCost(t *testing.T) {
t1 := time.Date(2012, time.February, 8, 22, 50, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 8, 22, 51, 50, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
result, _ := cd.GetCost()
expected := &CallCost{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", Cost: 0.1, ConnectFee: 0}
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
@@ -206,7 +206,7 @@ func TestMinutesCost(t *testing.T) {
func TestMaxSessionTimeNoUserBudget(t *testing.T) {
getter, _ := NewRedisStorage("tcp:127.0.0.1:6379", 10)
defer getter.Close()
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0723", StorageGetter: getter, Amount: 1000}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0723", storageGetter: getter, Amount: 1000}
result, err := cd.GetMaxSessionTime()
if result != 1000 || err != nil {
t.Errorf("Expected %v was %v", 1000, result)
@@ -216,7 +216,7 @@ func TestMaxSessionTimeNoUserBudget(t *testing.T) {
func TestMaxSessionTimeWithUserBudget(t *testing.T) {
getter, _ := NewRedisStorage("tcp:127.0.0.1:6379", 10)
defer getter.Close()
cd := &CallDescriptor{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", StorageGetter: getter, Amount: 5400}
cd := &CallDescriptor{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", storageGetter: getter, Amount: 5400}
result, err := cd.GetMaxSessionTime()
if result != 1080 || err != nil {
t.Errorf("Expected %v was %v", 1080, result)
@@ -226,13 +226,29 @@ func TestMaxSessionTimeWithUserBudget(t *testing.T) {
func TestMaxSessionTimeNoCredit(t *testing.T) {
getter, _ := NewRedisStorage("tcp:127.0.0.1:6379", 10)
defer getter.Close()
cd := &CallDescriptor{CstmId: "vdf", Subject: "broker", DestinationPrefix: "0723", StorageGetter: getter, Amount: 5400}
cd := &CallDescriptor{CstmId: "vdf", Subject: "broker", DestinationPrefix: "0723", storageGetter: getter, Amount: 5400}
result, err := cd.GetMaxSessionTime()
if result != 100 || err != nil {
t.Errorf("Expected %v was %v", 100, result)
}
}
func TestGetCostWithVolumeDiscount(t *testing.T) {
getter, _ := NewKyotoStorage("test.kch")
defer getter.Close()
vd1 := &VolumeDiscount{100, 10}
vd2 := &VolumeDiscount{500, 20}
seara := &TariffPlan{Id: "seara", SmsCredit: 100, VolumeDiscountThresholds: []*VolumeDiscount{vd1, vd2}}
rifsBudget := &UserBudget{Id: "other", Credit: 21, tariffPlan: seara, ResetDayOfTheMonth: 10, VolumeDiscountSeconds: 105}
t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0723", TimeStart: t1, TimeEnd: t2, storageGetter: getter, userBudget: rifsBudget}
callCost, err := cd.GetCost()
if callCost.Cost != 54.0 || err != nil {
t.Errorf("Expected %v was %v", 54.0, callCost)
}
}
/*********************************** BENCHMARKS ***************************************/
func BenchmarkRedisGetting(b *testing.B) {
b.StopTimer()
@@ -255,7 +271,7 @@ func BenchmarkRedisRestoring(b *testing.B) {
t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.RestoreFromStorage()
@@ -269,7 +285,7 @@ func BenchmarkRedisGetCost(b *testing.B) {
t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.GetCost()
@@ -283,7 +299,7 @@ func BenchmarkKyotoGetting(b *testing.B) {
t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
b.StartTimer()
for i := 0; i < b.N; i++ {
key := cd.GetKey()
@@ -298,7 +314,7 @@ func BenchmarkKyotoRestoring(b *testing.B) {
t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.RestoreFromStorage()
@@ -312,7 +328,7 @@ func BenchmarkSplitting(b *testing.B) {
t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
cd.RestoreFromStorage()
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -327,7 +343,7 @@ func BenchmarkKyotoGetCost(b *testing.B) {
t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.GetCost()
@@ -355,7 +371,7 @@ func BenchmarkMongoGetCost(b *testing.B) {
t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, StorageGetter: getter}
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.GetCost()
@@ -366,7 +382,7 @@ func BenchmarkKyotoSingleGetSessionTime(b *testing.B) {
b.StopTimer()
getter, _ := NewKyotoStorage("test.kch")
defer getter.Close()
cd := &CallDescriptor{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", StorageGetter: getter, Amount: 100}
cd := &CallDescriptor{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", storageGetter: getter, Amount: 100}
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.GetMaxSessionTime()
@@ -377,7 +393,7 @@ func BenchmarkKyotoMultipleGetSessionTime(b *testing.B) {
b.StopTimer()
getter, _ := NewKyotoStorage("test.kch")
defer getter.Close()
cd := &CallDescriptor{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", StorageGetter: getter, Amount: 5400}
cd := &CallDescriptor{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", storageGetter: getter, Amount: 5400}
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.GetMaxSessionTime()
@@ -388,7 +404,7 @@ func BenchmarkRedisSingleGetSessionTime(b *testing.B) {
b.StopTimer()
getter, _ := NewRedisStorage("", 10)
defer getter.Close()
cd := &CallDescriptor{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", StorageGetter: getter, Amount: 100}
cd := &CallDescriptor{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", storageGetter: getter, Amount: 100}
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.GetMaxSessionTime()
@@ -399,7 +415,7 @@ func BenchmarkRedisMultipleGetSessionTime(b *testing.B) {
b.StopTimer()
getter, _ := NewRedisStorage("", 10)
defer getter.Close()
cd := &CallDescriptor{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", StorageGetter: getter, Amount: 5400}
cd := &CallDescriptor{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", storageGetter: getter, Amount: 5400}
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.GetMaxSessionTime()
@@ -410,7 +426,7 @@ func BenchmarkMongoSingleGetSessionTime(b *testing.B) {
b.StopTimer()
getter, _ := NewMongoStorage("127.0.0.1", "test")
defer getter.Close()
cd := &CallDescriptor{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", StorageGetter: getter, Amount: 100}
cd := &CallDescriptor{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", storageGetter: getter, Amount: 100}
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.GetMaxSessionTime()
@@ -421,7 +437,7 @@ func BenchmarkMongoMultipleGetSessionTime(b *testing.B) {
b.StopTimer()
getter, _ := NewMongoStorage("127.0.0.1", "test")
defer getter.Close()
cd := &CallDescriptor{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", StorageGetter: getter, Amount: 5400}
cd := &CallDescriptor{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", storageGetter: getter, Amount: 5400}
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.GetMaxSessionTime()

View File

@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package timespans
import (
// "log"
"strconv"
"strings"
)
@@ -82,11 +83,13 @@ func (tp *TariffPlan) restore(input string) {
mb.restore(mbs)
tp.MinuteBuckets = append(tp.MinuteBuckets, mb)
}
for _, vdss := range strings.Split(elements[4], ",") {
vd := &VolumeDiscount{}
vds := strings.Split(vdss, "|")
vd.Volume, _ = strconv.ParseFloat(vds[0], 64)
vd.Discount, _ = strconv.ParseFloat(vds[1], 64)
tp.VolumeDiscountThresholds = append(tp.VolumeDiscountThresholds, vd)
if len(elements) > 4 {
for _, vdss := range strings.Split(elements[4], ",") {
vd := &VolumeDiscount{}
vds := strings.Split(vdss, "|")
vd.Volume, _ = strconv.ParseFloat(vds[0], 64)
vd.Discount, _ = strconv.ParseFloat(vds[1], 64)
tp.VolumeDiscountThresholds = append(tp.VolumeDiscountThresholds, vd)
}
}
}

Binary file not shown.

View File

@@ -49,7 +49,7 @@ func (ts *TimeSpan) GetDuration() time.Duration {
/*
Returns the cost of the timespan according to the relevant cost interval.
*/
func (ts *TimeSpan) GetCost() (cost float64) {
func (ts *TimeSpan) GetCost(cd *CallDescriptor) (cost float64) {
if ts.MinuteInfo != nil {
return ts.GetDuration().Seconds() * ts.MinuteInfo.Price
}
@@ -61,6 +61,13 @@ func (ts *TimeSpan) GetCost() (cost float64) {
} else {
cost = ts.GetDuration().Seconds() * ts.Interval.Price
}
if userBudget, err := cd.getUserBudget(); err == nil && userBudget != nil {
userBudget.mux.RLock()
if percentageDiscount, err := userBudget.getVolumeDiscount(cd.storageGetter); err == nil && percentageDiscount > 0 {
cost *= (100 - percentageDiscount) / 100
}
userBudget.mux.RUnlock()
}
return
}

View File

@@ -184,19 +184,22 @@ func TestSplitByActivationTime(t *testing.T) {
}
func TestTimespanGetCost(t *testing.T) {
getter, _ := NewKyotoStorage("test.kch")
defer getter.Close()
t1 := time.Date(2012, time.February, 5, 17, 45, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 5, 17, 55, 0, 0, time.UTC)
ts1 := TimeSpan{TimeStart: t1, TimeEnd: t2}
if ts1.GetCost() != 0 {
cd := &CallDescriptor{Subject: "other", storageGetter: getter}
if ts1.GetCost(cd) != 0 {
t.Error("No interval and still kicking")
}
ts1.Interval = &Interval{Price: 1}
if ts1.GetCost() != 600 {
t.Error("Expected 10 got ", ts1.GetCost())
if ts1.GetCost(cd) != 600 {
t.Error("Expected 10 got ", ts1.GetCost(cd))
}
ts1.Interval.BillingUnit = .1
if ts1.GetCost() != 6000 {
t.Error("Expected 6000 got ", ts1.GetCost())
if ts1.GetCost(cd) != 6000 {
t.Error("Expected 6000 got ", ts1.GetCost(cd))
}
}

View File

@@ -116,9 +116,12 @@ func (ub *UserBudget) getTariffPlan(storage StorageGetter) (tp *TariffPlan, err
return ub.tariffPlan, err
}
/*
Returns thevolume discount procentage according to the nuber of acumulated volume discount seconds.
*/
func (ub *UserBudget) getVolumeDiscount(storage StorageGetter) (float64, error) {
tariffPlan, err := ub.getTariffPlan(storage)
if err != nil {
if err != nil || tariffPlan == nil {
return 0.0, err
}
thresholds := len(tariffPlan.VolumeDiscountThresholds)

View File

@@ -315,7 +315,7 @@ func TestGetVolumeDiscountNotHaving(t *testing.T) {
}
}
func TestGetVolumeDiscountNotSteps(t *testing.T) {
func TestGetVolumeDiscountSteps(t *testing.T) {
vd1 := &VolumeDiscount{100, 11}
vd2 := &VolumeDiscount{500, 20}
seara := &TariffPlan{Id: "seara", SmsCredit: 100, VolumeDiscountThresholds: []*VolumeDiscount{vd1, vd2}}