Completing rankingDescSorter

This commit is contained in:
DanB
2024-10-17 13:07:01 +02:00
parent 1765be1247
commit 8b0279d341
3 changed files with 95 additions and 6 deletions

View File

@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package engine
import (
"sort"
"sync"
"github.com/cgrates/cgrates/utils"
@@ -102,7 +103,8 @@ type rankingSorter interface {
}
// rankingSortStats will return the list of sorted statIDs out of the sortingData map
func rankingSortStats(sortingType string, sortingParams []string, statMetrics map[string]map[string]float64) (sortedStatIDs []string, err error) {
func rankingSortStats(sortingType string, sortingParams []string,
statMetrics map[string]map[string]float64) (sortedStatIDs []string, err error) {
var rnkSrtr rankingSorter
if rnkSrtr, err = newRankingSorter(sortingType, sortingParams, statMetrics); err != nil {
return
@@ -119,18 +121,59 @@ func newRankingSorter(sortingType string, sortingParams []string,
default:
err = utils.ErrPrefixNotErrNotImplemented(sortingType)
return
case utils.MetaDescending:
return &rankingDescSorter{sortingParams, statMetrics}, nil
case utils.MetaDesc:
return newRankingDescSorter(sortingParams, statMetrics), nil
}
return
}
// newRankingDescSorter is a constructor for rankingDescSorter
func newRankingDescSorter(sortingParams []string,
statMetrics map[string]map[string]float64) (rkDsrtr *rankingDescSorter) {
rkDsrtr = &rankingDescSorter{
sortingParams,
statMetrics,
make([]string, 0, len(statMetrics))}
for statID := range rkDsrtr.statMetrics {
rkDsrtr.statIDs = append(rkDsrtr.statIDs, statID)
}
return
}
// rankingDescSorter will sort data descendently for metrics in sortingParams or randomly if all equal
type rankingDescSorter struct {
sortingParams []string
statMetrics map[string]map[string]float64
statIDs []string // list of keys of the statMetrics
}
func (rkDsrtr *rankingDescSorter) sortStatIDs() (statIDs []string) {
return
// sortStatIDs implements rankingSorter interface
func (rkDsrtr *rankingDescSorter) sortStatIDs() []string {
if len(rkDsrtr.statIDs) == 0 {
return rkDsrtr.statIDs
}
sort.Slice(rkDsrtr.statIDs, func(i, j int) bool {
for _, metricID := range rkDsrtr.sortingParams {
val1, hasMetric1 := rkDsrtr.statMetrics[rkDsrtr.statIDs[i]][metricID]
if !hasMetric1 {
return false
}
val2, hasMetric2 := rkDsrtr.statMetrics[rkDsrtr.statIDs[j]][metricID]
if !hasMetric2 {
return true
}
//in case we have the same value for the current metricID we skip to the next one
if val1 == val2 {
continue
}
if val1 > val2 {
return true
}
return false
}
//in case that we have the same value for all params we return randomly
return utils.BoolGenerator().RandomBool()
})
return rkDsrtr.statIDs
}

View File

@@ -0,0 +1,44 @@
/*
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
Copyright (C) ITsysCOM GmbH
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package engine
import (
"reflect"
"testing"
)
func TestRankingDescSorterSortStatIDs(t *testing.T) {
statMetrics := map[string]map[string]float64{
"STATS1": {"*acc": 12.1, "*tcc": 24.2},
"STATS2": {"*acc": 12.1, "*tcc": 24.3},
"STATS3": {"*acc": 10.1, "*tcc": 25.3},
}
sortMetrics := []string{"*acc", "*tcc"}
rdscSrtr := newRankingDescSorter(sortMetrics,statMetrics)
eStatIDs := []string{"STATS2", "STATS1", "STATS3"}
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, stats3 should come first
rdscSrtr = newRankingDescSorter(sortMetrics,statMetrics)
eStatIDs = []string{"STATS3", "STATS2", "STATS1"}
if statIDs := rdscSrtr.sortStatIDs(); !reflect.DeepEqual(eStatIDs, statIDs) {
t.Errorf("Expecting: %v, received %v", eStatIDs, statIDs)
}
}

View File

@@ -1019,6 +1019,8 @@ const (
MetaNodeID = "*node_id"
MetaAscending = "*ascending"
MetaDescending = "*descending"
MetaDesc = "*desc"
MetaAsc = "*asc"
)
// MetaMetrics