Adding reversed logic for sortingParams in RankingS

This commit is contained in:
DanB
2024-10-17 14:37:54 +02:00
parent 27ea475984
commit c1b0efd455
2 changed files with 65 additions and 16 deletions

View File

@@ -20,6 +20,7 @@ package engine
import (
"sort"
"strings"
"sync"
"github.com/cgrates/cgrates/utils"
@@ -131,8 +132,18 @@ func newRankingSorter(sortingType string, sortingParams []string,
// newRankingDescSorter is a constructor for rankingDescSorter
func newRankingDescSorter(sortingParams []string,
statMetrics map[string]map[string]float64) (rkDsrtr *rankingDescSorter) {
clnSp := make([]string, len(sortingParams))
sPReversed := make(utils.StringSet)
for i, sP := range sortingParams { // clean the sortingParams, out of param:false or param:true definitions
sPSlc := strings.Split(sP, utils.InInFieldSep)
clnSp[i] = sPSlc[0]
if len(sPSlc) > 1 && sPSlc[1] == utils.FalseStr {
sPReversed.Add(sPSlc[0]) // param defined as param:false which should be added to reversing comparison
}
}
rkDsrtr = &rankingDescSorter{
sortingParams,
clnSp,
sPReversed,
statMetrics,
make([]string, 0, len(statMetrics))}
for statID := range rkDsrtr.statMetrics {
@@ -143,8 +154,9 @@ func newRankingDescSorter(sortingParams []string,
// rankingDescSorter will sort data descendent for metrics in sortingParams or random if all equal
type rankingDescSorter struct {
sortingParams []string
statMetrics map[string]map[string]float64
sMetricIDs []string
sMetricRev utils.StringSet // list of exceptios for sortingParams, reverting the sorting logic
statMetrics map[string]map[string]float64
statIDs []string // list of keys of the statMetrics
}
@@ -155,7 +167,7 @@ func (rkDsrtr *rankingDescSorter) sortStatIDs() []string {
return rkDsrtr.statIDs
}
sort.Slice(rkDsrtr.statIDs, func(i, j int) bool {
for _, metricID := range rkDsrtr.sortingParams {
for _, metricID := range rkDsrtr.sMetricIDs {
val1, hasMetric1 := rkDsrtr.statMetrics[rkDsrtr.statIDs[i]][metricID]
if !hasMetric1 {
return false
@@ -168,10 +180,11 @@ func (rkDsrtr *rankingDescSorter) sortStatIDs() []string {
if val1 == val2 {
continue
}
if val1 > val2 {
return true
ret := val1 > val2
if rkDsrtr.sMetricRev.Has(metricID) {
ret = !ret
}
return false
return ret
}
//in case that we have the same value for all params we return randomly
return utils.BoolGenerator().RandomBool()
@@ -182,8 +195,18 @@ func (rkDsrtr *rankingDescSorter) sortStatIDs() []string {
// newRankingAscSorter is a constructor for rankingAscSorter
func newRankingAscSorter(sortingParams []string,
statMetrics map[string]map[string]float64) (rkASrtr *rankingAscSorter) {
clnSp := make([]string, len(sortingParams))
sPReversed := make(utils.StringSet)
for i, sP := range sortingParams { // clean the sortingParams, out of param:false or param:true definitions
sPSlc := strings.Split(sP, utils.InInFieldSep)
clnSp[i] = sPSlc[0]
if len(sPSlc) > 1 && sPSlc[1] == utils.FalseStr {
sPReversed.Add(sPSlc[0]) // param defined as param:false which should be added to reversing comparison
}
}
rkASrtr = &rankingAscSorter{
sortingParams,
clnSp,
sPReversed,
statMetrics,
make([]string, 0, len(statMetrics))}
for statID := range rkASrtr.statMetrics {
@@ -194,8 +217,9 @@ func newRankingAscSorter(sortingParams []string,
// rankingAscSorter will sort data ascendent for metrics in sortingParams or randomly if all equal
type rankingAscSorter struct {
sortingParams []string
statMetrics map[string]map[string]float64
sMetricIDs []string
sMetricRev utils.StringSet // list of exceptios for sortingParams, reverting the sorting logic
statMetrics map[string]map[string]float64
statIDs []string // list of keys of the statMetrics
}
@@ -206,7 +230,7 @@ func (rkASrtr *rankingAscSorter) sortStatIDs() []string {
return rkASrtr.statIDs
}
sort.Slice(rkASrtr.statIDs, func(i, j int) bool {
for _, metricID := range rkASrtr.sortingParams {
for _, metricID := range rkASrtr.sMetricIDs {
val1, hasMetric1 := rkASrtr.statMetrics[rkASrtr.statIDs[i]][metricID]
if !hasMetric1 {
return false
@@ -219,10 +243,11 @@ func (rkASrtr *rankingAscSorter) sortStatIDs() []string {
if val1 == val2 {
continue
}
if val2 > val1 {
return true
ret := val2 > val1
if rkASrtr.sMetricRev.Has(metricID) {
ret = !ret // reversed logic in case of metric:false in params
}
return false
return ret
}
//in case that we have the same value for all params we return randomly
return utils.BoolGenerator().RandomBool()

View File

@@ -36,12 +36,24 @@ func TestRankingDescSorterSortStatIDs(t *testing.T) {
if statIDs := rdscSrtr.sortStatIDs(); !reflect.DeepEqual(eStatIDs, statIDs) {
t.Errorf("Expecting: %v, received %v", eStatIDs, statIDs)
}
sortMetrics = []string{"*tcc", "*acc"} // changed the order of checks, stats4 should come first
sortMetrics = []string{"*acc:false", "*tcc"} // changed the order of checks, stats4 should come first
rdscSrtr = newRankingDescSorter(sortMetrics, statMetrics)
eStatIDs = []string{"STATS3", "STATS2", "STATS1", "STATS4"}
if statIDs := rdscSrtr.sortStatIDs(); !reflect.DeepEqual(eStatIDs, statIDs) {
t.Errorf("Expecting: %v, received %v", eStatIDs, statIDs)
}
sortMetrics = []string{"*tcc", "*acc:true"} // changed the order of checks, stats4 should come first
rdscSrtr = newRankingDescSorter(sortMetrics, statMetrics)
eStatIDs = []string{"STATS4", "STATS3", "STATS2", "STATS1"}
if statIDs := rdscSrtr.sortStatIDs(); !reflect.DeepEqual(eStatIDs, statIDs) {
t.Errorf("Expecting: %v, received %v", eStatIDs, statIDs)
}
sortMetrics = []string{"*tcc:false", "*acc"} // reversed *tcc which should consider ascendent instead of descendent
rdscSrtr = newRankingDescSorter(sortMetrics, statMetrics)
eStatIDs = []string{"STATS1", "STATS2", "STATS3", "STATS4"}
if statIDs := rdscSrtr.sortStatIDs(); !reflect.DeepEqual(eStatIDs, statIDs) {
t.Errorf("Expecting: %v, received %v", eStatIDs, statIDs)
}
}
func TestRankingAscSorterSortStatIDs(t *testing.T) {
@@ -57,10 +69,22 @@ func TestRankingAscSorterSortStatIDs(t *testing.T) {
if statIDs := rtAscSrtr.sortStatIDs(); !reflect.DeepEqual(eStatIDs, statIDs) {
t.Errorf("Expecting: %v, received %v", eStatIDs, statIDs)
}
sortMetrics = []string{"*tcc", "*acc"}
sortMetrics = []string{"*acc:false", "*tcc"}
rtAscSrtr = newRankingAscSorter(sortMetrics, statMetrics)
eStatIDs = []string{"STATS1", "STATS2", "STATS3", "STATS4"}
if statIDs := rtAscSrtr.sortStatIDs(); !reflect.DeepEqual(eStatIDs, statIDs) {
t.Errorf("Expecting: %v, received %v", eStatIDs, statIDs)
}
sortMetrics = []string{"*tcc", "*acc:true"}
rtAscSrtr = newRankingAscSorter(sortMetrics, statMetrics)
eStatIDs = []string{"STATS1", "STATS2", "STATS3", "STATS4"}
if statIDs := rtAscSrtr.sortStatIDs(); !reflect.DeepEqual(eStatIDs, statIDs) {
t.Errorf("Expecting: %v, received %v", eStatIDs, statIDs)
}
sortMetrics = []string{"*tcc:false", "*acc"}
rtAscSrtr = newRankingAscSorter(sortMetrics, statMetrics)
eStatIDs = []string{"STATS4", "STATS3", "STATS2", "STATS1"}
if statIDs := rtAscSrtr.sortStatIDs(); !reflect.DeepEqual(eStatIDs, statIDs) {
t.Errorf("Expecting: %v, received %v", eStatIDs, statIDs)
}
}