implemented received call bonus

This commit is contained in:
Radu Ioan Fericean
2012-02-29 16:22:06 +02:00
parent 0bd20b3a22
commit 02430bef24
7 changed files with 103 additions and 26 deletions

View File

@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package timespans
import (
// "log"
"math"
"strconv"
"strings"
@@ -47,11 +48,11 @@ func (mb *MinuteBucket) store() (result string) {
De-serializes the minute bucket for the storage. Used for key-value storages.
*/
func (mb *MinuteBucket) restore(input string) {
mbse := strings.Split(input, "|")
mb.Seconds, _ = strconv.ParseFloat(mbse[0], 64)
mb.Priority, _ = strconv.Atoi(mbse[1])
mb.Price, _ = strconv.ParseFloat(mbse[2], 64)
mb.DestinationId = mbse[3]
elements := strings.Split(input, "|")
mb.Seconds, _ = strconv.ParseFloat(elements[0], 64)
mb.Priority, _ = strconv.Atoi(elements[1])
mb.Price, _ = strconv.ParseFloat(elements[2], 64)
mb.DestinationId = elements[3]
}
/*

View File

@@ -45,13 +45,6 @@ type VolumeDiscount struct {
Discount float64 // procentage
}
type RecivedCallBonus struct {
Credit float64
SmsCredit float64
Traffic float64
MinuteBuckets *MinuteBucket
}
/*
Serializes the tariff plan for the storage. Used for key-value storages.
*/
@@ -59,13 +52,19 @@ func (tp *TariffPlan) store() (result string) {
result += strconv.FormatFloat(tp.SmsCredit, 'f', -1, 64) + ";"
result += strconv.FormatFloat(tp.Traffic, 'f', -1, 64) + ";"
result += strconv.FormatFloat(tp.ReceivedCallSecondsLimit, 'f', -1, 64) + ";"
if tp.RecivedCallBonus == nil {
tp.RecivedCallBonus = &RecivedCallBonus{}
}
result += tp.RecivedCallBonus.store() + ";"
for i, mb := range tp.MinuteBuckets {
if i > 0 {
result += ","
}
result += mb.store()
}
result += ";"
if tp.VolumeDiscountThresholds != nil {
result += ";"
}
for i, vd := range tp.VolumeDiscountThresholds {
if i > 0 {
result += ","
@@ -84,13 +83,15 @@ func (tp *TariffPlan) restore(input string) {
tp.SmsCredit, _ = strconv.ParseFloat(elements[0], 64)
tp.Traffic, _ = strconv.ParseFloat(elements[1], 64)
tp.ReceivedCallSecondsLimit, _ = strconv.ParseFloat(elements[2], 64)
for _, mbs := range strings.Split(elements[3], ",") {
tp.RecivedCallBonus = &RecivedCallBonus{}
tp.RecivedCallBonus.restore(elements[3])
for _, mbs := range strings.Split(elements[4], ",") {
mb := &MinuteBucket{}
mb.restore(mbs)
tp.MinuteBuckets = append(tp.MinuteBuckets, mb)
}
if len(elements) > 4 {
for _, vdss := range strings.Split(elements[4], ",") {
if len(elements) > 5 {
for _, vdss := range strings.Split(elements[5], ",") {
vd := &VolumeDiscount{}
vds := strings.Split(vdss, "|")
vd.Volume, _ = strconv.ParseFloat(vds[0], 64)
@@ -99,3 +100,41 @@ func (tp *TariffPlan) restore(input string) {
}
}
}
/*
Structure to be filled for each tariff plan with the bonus value for received calls minutes.
*/
type RecivedCallBonus struct {
Credit float64
SmsCredit float64
Traffic float64
MinuteBucket *MinuteBucket
}
/*
Serializes the tariff plan for the storage. Used for key-value storages.
*/
func (rcb *RecivedCallBonus) store() (result string) {
result += strconv.FormatFloat(rcb.Credit, 'f', -1, 64) + ","
result += strconv.FormatFloat(rcb.SmsCredit, 'f', -1, 64) + ","
result += strconv.FormatFloat(rcb.Traffic, 'f', -1, 64)
if rcb.MinuteBucket != nil {
result += ","
result += rcb.MinuteBucket.store()
}
return
}
/*
De-serializes the tariff plan for the storage. Used for key-value storages.
*/
func (rcb *RecivedCallBonus) restore(input string) {
elements := strings.Split(input, ",")
rcb.Credit, _ = strconv.ParseFloat(elements[0], 64)
rcb.SmsCredit, _ = strconv.ParseFloat(elements[1], 64)
rcb.Traffic, _ = strconv.ParseFloat(elements[2], 64)
if len(elements) > 3 {
rcb.MinuteBucket = &MinuteBucket{}
rcb.MinuteBucket.restore(elements[3])
}
}

View File

@@ -24,8 +24,14 @@ import (
func TestTariffPlanStoreRestore(t *testing.T) {
b1 := &MinuteBucket{Seconds: 10, Priority: 10, Price: 0.01, DestinationId: "nationale"}
b2 := &MinuteBucket{Seconds: 100, Priority: 20, Price: 0.0, DestinationId: "retea"}
rcb := &RecivedCallBonus{Credit: 100}
vd := &VolumeDiscount{100, 10}
seara := &TariffPlan{Id: "seara_voo", SmsCredit: 100, ReceivedCallSecondsLimit: 0, MinuteBuckets: []*MinuteBucket{b1, b2}, VolumeDiscountThresholds: []*VolumeDiscount{vd}}
seara := &TariffPlan{Id: "seara_voo",
SmsCredit: 100,
ReceivedCallSecondsLimit: 0,
RecivedCallBonus: rcb,
MinuteBuckets: []*MinuteBucket{b1, b2},
VolumeDiscountThresholds: []*VolumeDiscount{vd}}
s := seara.store()
tp1 := &TariffPlan{Id: "seara_voo"}
tp1.restore(s)
@@ -82,7 +88,7 @@ func BenchmarkTariffPlanKyotoStoreRestore(b *testing.B) {
defer getter.Close()
b1 := &MinuteBucket{Seconds: 10, Priority: 10, Price: 0.01, DestinationId: "nationale"}
b2 := &MinuteBucket{Seconds: 100, Priority: 20, Price: 0.0, DestinationId: "retea"}
seara := &TariffPlan{Id: "seara", SmsCredit: 100, MinuteBuckets: []*MinuteBucket{b1, b2}}
seara := &TariffPlan{Id: "seara_other", SmsCredit: 100, MinuteBuckets: []*MinuteBucket{b1, b2}}
for i := 0; i < b.N; i++ {
getter.SetTariffPlan(seara)
getter.GetTariffPlan(seara.Id)
@@ -94,7 +100,7 @@ func BenchmarkTariffPlanRedisStoreRestore(b *testing.B) {
defer getter.Close()
b1 := &MinuteBucket{Seconds: 10, Priority: 10, Price: 0.01, DestinationId: "nationale"}
b2 := &MinuteBucket{Seconds: 100, Priority: 20, Price: 0.0, DestinationId: "retea"}
seara := &TariffPlan{Id: "seara", SmsCredit: 100, MinuteBuckets: []*MinuteBucket{b1, b2}}
seara := &TariffPlan{Id: "seara_other", SmsCredit: 100, MinuteBuckets: []*MinuteBucket{b1, b2}}
for i := 0; i < b.N; i++ {
getter.SetTariffPlan(seara)
getter.GetTariffPlan(seara.Id)
@@ -106,7 +112,7 @@ func BenchmarkTariffPlanMongoStoreRestore(b *testing.B) {
defer getter.Close()
b1 := &MinuteBucket{Seconds: 10, Priority: 10, Price: 0.01, DestinationId: "nationale"}
b2 := &MinuteBucket{Seconds: 100, Priority: 20, Price: 0.0, DestinationId: "retea"}
seara := &TariffPlan{Id: "seara", SmsCredit: 100, MinuteBuckets: []*MinuteBucket{b1, b2}}
seara := &TariffPlan{Id: "seara_other", SmsCredit: 100, MinuteBuckets: []*MinuteBucket{b1, b2}}
for i := 0; i < b.N; i++ {
getter.SetTariffPlan(seara)
getter.GetTariffPlan(seara.Id)

Binary file not shown.

View File

@@ -1,14 +1,17 @@
[
{"Id":"seara","SmsCredit":100,"ReceivedCallsSecondsLimit": 100,
"RecivedCallBonus" : {"Credit": 100},
"MinuteBuckets":
[{"Seconds":10,"Priority":10,"Price":0.01,"DestinationId":"nationale"}, {"Seconds":100,"Priority":20,"Price":0,"DestinationId":"retea"}],
"VolumeDiscountThresholds":
[{"Volume": 100, "Discount": 10},{"Volume": 500, "Discount": 15},{"Volume": 1000, "Discount": 20}]
},
{"Id":"dimineata","SmsCredit":100,"ReceivedCallsSecondsLimit": 100,
"RecivedCallBonus" : {"Credit": 100},
"MinuteBuckets":
[{"Seconds":100,"Priority":10,"Price":0.01,"DestinationId":"nationale"}, {"Seconds":1000,"Priority":20,"Price":0,"DestinationId":"retea"}],
"VolumeDiscountThresholds":
[{"Volume": 100, "Discount": 10},{"Volume": 500, "Discount": 15},{"Volume": 1000, "Discount": 20}]
}
]

View File

@@ -80,7 +80,10 @@ func (ub *UserBudget) store() (result string) {
result += strconv.FormatFloat(ub.VolumeDiscountSeconds, 'f', -1, 64) + ";"
result += strconv.FormatFloat(ub.ReceivedCallSeconds, 'f', -1, 64) + ";"
result += strconv.Itoa(ub.ResetDayOfTheMonth) + ";"
result += ub.TariffPlanId + ";"
result += ub.TariffPlanId
if ub.MinuteBuckets != nil {
result += ";"
}
for i, mb := range ub.MinuteBuckets {
if i > 0 {
result += ","
@@ -102,10 +105,12 @@ func (ub *UserBudget) restore(input string) {
ub.ReceivedCallSeconds, _ = strconv.ParseFloat(elements[4], 64)
ub.ResetDayOfTheMonth, _ = strconv.Atoi(elements[5])
ub.TariffPlanId = elements[6]
for _, mbs := range strings.Split(elements[7], ",") {
mb := &MinuteBucket{}
mb.restore(mbs)
ub.MinuteBuckets = append(ub.MinuteBuckets, mb)
if len(elements) > 7 {
for _, mbs := range strings.Split(elements[7], ",") {
mb := &MinuteBucket{}
mb.restore(mbs)
ub.MinuteBuckets = append(ub.MinuteBuckets, mb)
}
}
}
@@ -249,7 +254,18 @@ func (ub *UserBudget) addReceivedCallSeconds(sg StorageGetter, amount float64) e
if tariffPlan, err := ub.getTariffPlan(sg); tariffPlan != nil && err == nil {
if ub.ReceivedCallSeconds >= tariffPlan.ReceivedCallSecondsLimit {
ub.ReceivedCallSeconds -= tariffPlan.ReceivedCallSecondsLimit
// do the dew
if tariffPlan.RecivedCallBonus != nil { // apply the bonus
ub.Credit += tariffPlan.RecivedCallBonus.Credit
ub.SmsCredit += tariffPlan.RecivedCallBonus.SmsCredit
ub.Traffic += tariffPlan.RecivedCallBonus.Traffic
if tariffPlan.RecivedCallBonus.MinuteBucket != nil {
for _, mb := range ub.MinuteBuckets {
if mb.DestinationId == tariffPlan.RecivedCallBonus.MinuteBucket.DestinationId {
mb.Seconds += tariffPlan.RecivedCallBonus.MinuteBucket.Seconds
}
}
}
}
}
}
return sg.SetUserBudget(ub)

View File

@@ -376,6 +376,18 @@ func TestGetVolumeDiscountSteps(t *testing.T) {
}
}
func TestRecivedCallsBonus(t *testing.T) {
getter, _ := NewKyotoStorage("test.kch")
defer getter.Close()
rcb := &RecivedCallBonus{Credit: 100}
seara := &TariffPlan{Id: "seara_voo", SmsCredit: 100, ReceivedCallSecondsLimit: 10, RecivedCallBonus: rcb}
rifsBudget := &UserBudget{Id: "other", Credit: 21, tariffPlan: seara, ResetDayOfTheMonth: 10, ReceivedCallSeconds: 1}
err := rifsBudget.addReceivedCallSeconds(getter, 12)
if err != nil || rifsBudget.Credit != 121 || rifsBudget.ReceivedCallSeconds != 3 {
t.Error("Wrong Received call bonus procedure: ", rifsBudget)
}
}
/*********************************** Benchmarks *******************************/
func BenchmarkGetSecondForPrefix(b *testing.B) {