better rate intervals sorting according to weight

should solve the issue #424
This commit is contained in:
Radu Ioan Fericean
2016-04-12 23:17:01 +03:00
parent bafa9d9802
commit 6cf36e5be0
3 changed files with 114 additions and 18 deletions

View File

@@ -360,23 +360,6 @@ func (ri *RateInterval) GetMaxCost() (float64, string) {
// Structure to store intervals according to weight
type RateIntervalList []*RateInterval
func (il RateIntervalList) Len() int {
return len(il)
}
func (il RateIntervalList) Swap(i, j int) {
il[i], il[j] = il[j], il[i]
}
// we need higher weights earlyer in the list
func (il RateIntervalList) Less(j, i int) bool {
return il[i].Weight < il[j].Weight //|| il[i].Timing.StartTime > il[j].Timing.StartTime
}
func (il RateIntervalList) Sort() {
sort.Sort(il)
}
// Structure to store intervals according to weight
type RateIntervalTimeSorter struct {
referenceTime time.Time
@@ -393,6 +376,9 @@ func (il *RateIntervalTimeSorter) Swap(i, j int) {
// we need higher weights earlyer in the list
func (il *RateIntervalTimeSorter) Less(j, i int) bool {
if il.ris[i].Weight < il.ris[j].Weight {
return il.ris[i].Weight < il.ris[j].Weight
}
t1 := il.ris[i].Timing.getLeftMargin(il.referenceTime)
t2 := il.ris[j].Timing.getLeftMargin(il.referenceTime)
return t1.After(t2)

View File

@@ -92,28 +92,36 @@ type RatingInfo struct {
// SelectRatingIntevalsForTimespan orders rate intervals in time preserving only those which aply to the specified timestamp
func (ri RatingInfo) SelectRatingIntevalsForTimespan(ts *TimeSpan) (result RateIntervalList) {
ri.RateIntervals.Sort()
sorter := &RateIntervalTimeSorter{referenceTime: ts.TimeStart, ris: ri.RateIntervals}
rateIntervals := sorter.Sort()
// get the rating interval closest to begining of timespan
var delta time.Duration = -1
var bestRateIntervalIndex int
var bestIntervalWeight float64
for index, rateInterval := range rateIntervals {
if !rateInterval.Contains(ts.TimeStart, false) {
continue
}
if rateInterval.Weight < bestIntervalWeight {
break // don't consider lower weights'
}
startTime := rateInterval.Timing.getLeftMargin(ts.TimeStart)
tmpDelta := ts.TimeStart.Sub(startTime)
if (startTime.Before(ts.TimeStart) ||
startTime.Equal(ts.TimeStart)) &&
(delta == -1 || tmpDelta < delta) {
bestRateIntervalIndex = index
bestIntervalWeight = rateInterval.Weight
delta = tmpDelta
}
}
result = append(result, rateIntervals[bestRateIntervalIndex])
// check if later rating intervals influence this timespan
//log.Print("RIS: ", utils.ToIJSON(rateIntervals))
for i := bestRateIntervalIndex + 1; i < len(rateIntervals); i++ {
if rateIntervals[i].Weight < bestIntervalWeight {
break // don't consider lower weights'
}
startTime := rateIntervals[i].Timing.getLeftMargin(ts.TimeStart)
if startTime.Before(ts.TimeEnd) {
result = append(result, rateIntervals[i])

View File

@@ -285,6 +285,108 @@ func TestRatingProfileYearMonthDay(t *testing.T) {
}
}
func TestRatingProfileWeighted(t *testing.T) {
ri := &RatingInfo{
RateIntervals: RateIntervalList{
&RateInterval{
Timing: &RITiming{
StartTime: "09:00:00",
},
Weight: 10,
},
&RateInterval{
Timing: &RITiming{
StartTime: "00:00:00",
},
Weight: 10,
},
&RateInterval{
Timing: &RITiming{
StartTime: "19:00:00",
},
Weight: 10,
},
&RateInterval{
Timing: &RITiming{
Years: utils.Years{2016},
Months: utils.Months{1},
MonthDays: utils.MonthDays{6},
WeekDays: utils.WeekDays{},
StartTime: "00:00:00",
},
Weight: 11,
},
},
}
ts := &TimeSpan{
TimeStart: time.Date(2016, 1, 6, 23, 40, 0, 0, time.UTC),
TimeEnd: time.Date(2016, 1, 6, 23, 45, 30, 0, time.UTC),
}
rIntervals := ri.SelectRatingIntevalsForTimespan(ts)
if len(rIntervals) != 1 ||
rIntervals[0].Timing.StartTime != "00:00:00" ||
rIntervals[0].Weight != 11 {
t.Error("Wrong interval list: ", utils.ToIJSON(rIntervals))
}
}
func TestRatingProfileWeightedMultiple(t *testing.T) {
ri := &RatingInfo{
RateIntervals: RateIntervalList{
&RateInterval{
Timing: &RITiming{
StartTime: "09:00:00",
},
Weight: 10,
},
&RateInterval{
Timing: &RITiming{
StartTime: "00:00:00",
},
Weight: 10,
},
&RateInterval{
Timing: &RITiming{
StartTime: "19:00:00",
},
Weight: 10,
},
&RateInterval{
Timing: &RITiming{
Years: utils.Years{2016},
Months: utils.Months{1},
MonthDays: utils.MonthDays{6},
WeekDays: utils.WeekDays{},
StartTime: "00:00:00",
},
Weight: 11,
},
&RateInterval{
Timing: &RITiming{
Years: utils.Years{2016},
Months: utils.Months{1},
MonthDays: utils.MonthDays{6},
WeekDays: utils.WeekDays{},
StartTime: "18:00:00",
},
Weight: 11,
},
},
}
ts := &TimeSpan{
TimeStart: time.Date(2016, 1, 6, 17, 40, 0, 0, time.UTC),
TimeEnd: time.Date(2016, 1, 6, 23, 45, 30, 0, time.UTC),
}
rIntervals := ri.SelectRatingIntevalsForTimespan(ts)
if len(rIntervals) != 2 ||
rIntervals[0].Timing.StartTime != "00:00:00" ||
rIntervals[0].Weight != 11 ||
rIntervals[1].Timing.StartTime != "18:00:00" ||
rIntervals[1].Weight != 11 {
t.Error("Wrong interval list: ", utils.ToIJSON(rIntervals))
}
}
func TestRatingProfileSubjectPrefixMatching(t *testing.T) {
rpSubjectPrefixMatching = true
rp, err := RatingProfileSubjectPrefixMatching("*out:cgrates.org:data:rif")