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 8148a6330..33669ac51 100644 Binary files a/timespans/test.kch and b/timespans/test.kch differ 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