From 4b1f4884445b8823d7a777bbfe3e67e9b680c609 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Thu, 23 Feb 2012 20:37:50 +0200 Subject: [PATCH] we have the first GetMaxSessionTime for prepaid ;) --- timespans/calldesc.go | 37 +++++++++++++++++-------- timespans/calldesc_test.go | 25 +++++++++++++++-- timespans/test.kch | Bin 6298712 -> 6298792 bytes timespans/test_activation_periods.json | 7 +++++ timespans/test_userbudgets.json | 5 ++-- timespans/timespans.go | 6 +++- 6 files changed, 63 insertions(+), 17 deletions(-) diff --git a/timespans/calldesc.go b/timespans/calldesc.go index cc6307a43..026645a3a 100644 --- a/timespans/calldesc.go +++ b/timespans/calldesc.go @@ -2,7 +2,7 @@ package timespans import ( "fmt" - //"log" + // "log" "math" "time" ) @@ -209,19 +209,32 @@ Returns the cost of a second in the present time conditions. func (cd *CallDescriptor) GetMaxSessionTime(maxSessionSeconds int) (seconds int, err error) { _, err = cd.RestoreFromStorage() now := time.Now() - maxDuration, _ := time.ParseDuration(fmt.Sprintf("%vs", maxSessionSeconds)) - ts := &TimeSpan{TimeStart: now, TimeEnd: now.Add(maxDuration)} - timespans := cd.splitTimeSpan(ts) - - cost := 0.0 - for i, ts := range timespans { - if i == 0 { - cost += ts.Interval.ConnectFee - } - cost += ts.GetCost() + availableCredit := 0.0 + if userBudget, err := cd.StorageGetter.GetUserBudget(cd.Subject); err == nil && userBudget != nil { + availableCredit = userBudget.Credit + } else { + return maxSessionSeconds, err } + orig_maxSessionSeconds := maxSessionSeconds + for i := 0; i < 10; i++ { + maxDuration, _ := time.ParseDuration(fmt.Sprintf("%vs", maxSessionSeconds)) + ts := &TimeSpan{TimeStart: now, TimeEnd: now.Add(maxDuration)} + timespans := cd.splitTimeSpan(ts) - return + cost := 0.0 + for i, ts := range timespans { + if ts.MinuteInfo == nil && i == 0 { + cost += ts.Interval.ConnectFee + } + cost += ts.GetCost() + } + if cost < availableCredit { + return maxSessionSeconds, nil + } else { //decrease the period by 10% and try again + maxSessionSeconds -= int(float64(orig_maxSessionSeconds) * 0.1) + } + } + return 0, nil } /* diff --git a/timespans/calldesc_test.go b/timespans/calldesc_test.go index 2238bc6f8..459b5ecad 100644 --- a/timespans/calldesc_test.go +++ b/timespans/calldesc_test.go @@ -173,15 +173,36 @@ func TestMinutesCost(t *testing.T) { defer getter.Close() 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) + 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} result, _ := cd.GetCost() - expected := &CallCost{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", Cost: 0, ConnectFee: 0} + expected := &CallCost{CstmId: "vdf", Subject: "minutosu", DestinationPrefix: "0723", Cost: 0.1, ConnectFee: 0} if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee { + t.Log(result.Timespans[0]) t.Errorf("Expected %v was %v", expected, result) } } +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} + result, err := cd.GetMaxSessionTime(1000) + if result != 1000 || err != nil { + t.Errorf("Expected %v was %v", 1000, result) + } +} + +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} + result, err := cd.GetMaxSessionTime(5400) + if result != 1080 || err != nil { + t.Errorf("Expected %v was %v", 1080, result) + } +} + /*********************************** BENCHMARKS ***************************************/ func BenchmarkRedisGetting(b *testing.B) { b.StopTimer() diff --git a/timespans/test.kch b/timespans/test.kch index 8148a63308a3a5993637ce687bb5a8749a6356cb..33669ac51b55a468222808efb46ec9fe039ac02e 100644 GIT binary patch delta 493 zcmYk(H%~%g7{zh9Sg>Okxrhz1`+{BUz3a7iuZfyCSR&#K!y5({oiH)(Z0cap$&o=n zfC(SO)xSm)pX7I@lbqrCc=j8^FMi{dGdVr(`*bxN5KHQB z^r8>_7{DNgFpLq5VhrP$z$B(HjTy{h4jSgMfJH1}87o-D8rHFaO>AL168+p!Dy+)S zM}8yAaj|#Md31Q}J3sOILUxN@7c#5*nBzV1f6e6ntGHbr;c*F%cYpV6H&n0cwO6DqANQ6rgiRig$D)S?dcXh0*H;6yW8(26#gaG@O?=tLK~GdY+0@jaom zvZR&uEtt#~yy$@sz34+f1~3RehA<3403#U17{)PyNlalHGnmC3=26^Pz#>9e!ZKE{ ziZ!ewj16pJ3)|SiF7~jG103QA$2h?$&Je*lE^vt`u5g{n7jCQ`r}1~mf7$$ZxA(E< Pho@M|Ybr@OOcnkG*h|>> diff --git a/timespans/test_activation_periods.json b/timespans/test_activation_periods.json index e19dd784a..fa69ba85b 100644 --- a/timespans/test_activation_periods.json +++ b/timespans/test_activation_periods.json @@ -29,5 +29,12 @@ ] } ] +}, +{"TOR": 0,"CstmId":"vdf","Subject":"minutosu","DestinationPrefix":"0723", "ActivationPeriods": [ + {"ActivationTime": "2012-01-01T00:00:00Z", "Intervals": [ + {"BillingUnit":60,"ConnectFee":0,"Month":0,"MonthDay":0,"Ponder":0,"Price":1,"StartTime":"","EndTime":""} + ] + } + ] } ] diff --git a/timespans/test_userbudgets.json b/timespans/test_userbudgets.json index fd6e6c9f6..36056a68e 100644 --- a/timespans/test_userbudgets.json +++ b/timespans/test_userbudgets.json @@ -1,4 +1,5 @@ [ -{"Id":"minutosu","Credit":21,"SmsCredit":0,"ResetDayOfTheMonth":10,"TariffPlanId":"","MinuteBuckets": [{"Seconds":10,"Priority":10,"Price":0.01,"DestinationId":"nationale"}, - {"Seconds":100,"Priority":20,"Price":0,"DestinationId":"retea"}]} +{"Id":"minutosu","Credit":21,"SmsCredit":0,"ResetDayOfTheMonth":10,"TariffPlanId":"seara","MinuteBuckets": + [{"Seconds":10,"Priority":10,"Price":0.01,"DestinationId":"nationale"}, + {"Seconds":100,"Priority":20,"Price":0,"DestinationId":"retea"}]} ] diff --git a/timespans/timespans.go b/timespans/timespans.go index 09e44a6ed..37f510978 100644 --- a/timespans/timespans.go +++ b/timespans/timespans.go @@ -19,6 +19,7 @@ type TimeSpan struct { type MinuteInfo struct { DestinationId string Quantity float64 + Price float64 } /* @@ -32,6 +33,9 @@ func (ts *TimeSpan) GetDuration() time.Duration { Returns the cost of the timespan according to the relevant cost interval. */ func (ts *TimeSpan) GetCost() (cost float64) { + if ts.MinuteInfo != nil { + return ts.GetDuration().Seconds() * ts.MinuteInfo.Price + } if ts.Interval == nil { return 0 } @@ -123,7 +127,7 @@ Splits the given timespan on activation period's activation time. */ func (ts *TimeSpan) SplitByMinuteBucket(mb *MinuteBucket) (newTs *TimeSpan) { s := ts.GetDuration().Seconds() - ts.MinuteInfo = &MinuteInfo{mb.DestinationId, s} + ts.MinuteInfo = &MinuteInfo{mb.DestinationId, s, mb.Price} if s <= mb.Seconds { mb.Seconds -= s return nil