diff --git a/README b/README index 607bd78e7..62ae63565 100644 --- a/README +++ b/README @@ -1 +1,10 @@ -Rating system for telecom providers. +Rating system designed to be used in VoIP Carriers World. + +Features +- Fast RatingEngine, holds all rating information into memory +- Unlimited spanned timebased rating: considers both ActiveFrom/RateStartsAt +- Unlimited rate profiles chanining for fallback +- Rating Fields: ConnectFee, RateIn, RateOut +- High accuracy rating: configurable to miliseconds +- Flexible rates storage - plugin based rates loading +- Flexibility to rate various information from the cdrs as rating subject. diff --git a/timespans/userbudget.go b/timespans/userbudget.go new file mode 100644 index 000000000..8a40716ba --- /dev/null +++ b/timespans/userbudget.go @@ -0,0 +1,65 @@ +package timespans + +import ( + "log" + "math" +) + +/* +Structure conatining information about user's credit (minutes, cents, sms...).' +*/ +type UserBudget struct { + id string + minuteBuckets []*MinuteBucket + credit float64 + smsCredit int + tariffPlan *TariffPlan + resetDayOfTheMonth int +} + +/* +Returns user's avaliable minutes for the specified destination +*/ +func (ub *UserBudget) GetSecondsForPrefix(prefix string) (seconds int) { + if len(ub.minuteBuckets) == 0 { + log.Print("There are no minute buckets to check for user", ub.id) + return + } + bestBucket := ub.minuteBuckets[0] + + for _, mb := range ub.minuteBuckets { + if mb.containsPrefix(prefix) && mb.priority > bestBucket.priority { + bestBucket = mb + } + } + seconds = bestBucket.seconds + if bestBucket.price > 0 { + seconds = int(math.Min(ub.credit/bestBucket.price, float64(seconds))) + } + return +} + +type Destination struct { + id string + prefixes []string +} + +type MinuteBucket struct { + seconds int + priority int + price float64 + destination *Destination +} + +func (mb *MinuteBucket) containsPrefix(prefix string) bool { + for _, p := range mb.destination.prefixes { + if prefix == p { + return true + } + } + return false +} + +type TariffPlan struct { + minuteBuckets []*MinuteBucket +} diff --git a/timespans/userbudget_test.go b/timespans/userbudget_test.go new file mode 100644 index 000000000..381b460ae --- /dev/null +++ b/timespans/userbudget_test.go @@ -0,0 +1,51 @@ +package timespans + +import ( + "testing" +) + +var ( + nationale = &Destination{id: "nationale", prefixes: []string{"0257", "0256", "0723"}} + retea = &Destination{id: "retea", prefixes: []string{"0723", "0724"}} +) + +func TestGetSeconds(t *testing.T) { + b1 := &MinuteBucket{seconds: 10, priority: 10, destination: nationale} + b2 := &MinuteBucket{seconds: 100, priority: 20, destination: retea} + tf1 := &TariffPlan{minuteBuckets: []*MinuteBucket{b1, b2}} + + ub1 := &UserBudget{id: "rif", minuteBuckets: []*MinuteBucket{b1, b2}, credit: 200, tariffPlan: tf1, resetDayOfTheMonth: 10} + seconds := ub1.GetSecondsForPrefix("0723") + expected := 100 + if seconds != expected { + t.Errorf("Expected %v was %v", expected, seconds) + } +} + +func TestGetPricedSeconds(t *testing.T) { + b1 := &MinuteBucket{seconds: 10, price: 10, priority: 10, destination: nationale} + b2 := &MinuteBucket{seconds: 100, price: 1, priority: 20, destination: retea} + tf1 := &TariffPlan{minuteBuckets: []*MinuteBucket{b1, b2}} + + ub1 := &UserBudget{id: "rif", minuteBuckets: []*MinuteBucket{b1, b2}, credit: 21, tariffPlan: tf1, resetDayOfTheMonth: 10} + seconds := ub1.GetSecondsForPrefix("0723") + expected := 21 + if seconds != expected { + t.Errorf("Expected %v was %v", expected, seconds) + } +} + +/*********************************** Benchmarks *******************************/ + +func BenchmarkGetSecondForPrefix(b *testing.B) { + b.StopTimer() + b1 := &MinuteBucket{seconds: 10, price: 10, priority: 10, destination: nationale} + b2 := &MinuteBucket{seconds: 100, price: 1, priority: 20, destination: retea} + tf1 := &TariffPlan{minuteBuckets: []*MinuteBucket{b1, b2}} + + ub1 := &UserBudget{id: "rif", minuteBuckets: []*MinuteBucket{b1, b2}, credit: 21, tariffPlan: tf1, resetDayOfTheMonth: 10} + b.StartTimer() + for i := 0; i < b.N; i++ { + ub1.GetSecondsForPrefix("0723") + } +}