Round language stats percentage using largest remainder (#22026)
Fix #22023 I've changed how the percentages for the language statistics are rounded because they did not always add up to 100% Now it's done with the largest remainder method, which makes sure that total is 100% Co-authored-by: Lauris BH <lauris@nix.lv>
This commit is contained in:
parent
0a85537c79
commit
cf27403e18
|
@ -6,6 +6,7 @@ package repo
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"math"
|
"math"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
@ -43,7 +44,7 @@ func (stats LanguageStatList) LoadAttributes() {
|
||||||
|
|
||||||
func (stats LanguageStatList) getLanguagePercentages() map[string]float32 {
|
func (stats LanguageStatList) getLanguagePercentages() map[string]float32 {
|
||||||
langPerc := make(map[string]float32)
|
langPerc := make(map[string]float32)
|
||||||
var otherPerc float32 = 100
|
var otherPerc float32
|
||||||
var total int64
|
var total int64
|
||||||
|
|
||||||
for _, stat := range stats {
|
for _, stat := range stats {
|
||||||
|
@ -51,21 +52,52 @@ func (stats LanguageStatList) getLanguagePercentages() map[string]float32 {
|
||||||
}
|
}
|
||||||
if total > 0 {
|
if total > 0 {
|
||||||
for _, stat := range stats {
|
for _, stat := range stats {
|
||||||
perc := float32(math.Round(float64(stat.Size)/float64(total)*1000) / 10)
|
perc := float32(float64(stat.Size) / float64(total) * 100)
|
||||||
if perc <= 0.1 {
|
if perc <= 0.1 {
|
||||||
|
otherPerc += perc
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
otherPerc -= perc
|
|
||||||
langPerc[stat.Language] = perc
|
langPerc[stat.Language] = perc
|
||||||
}
|
}
|
||||||
otherPerc = float32(math.Round(float64(otherPerc)*10) / 10)
|
|
||||||
}
|
}
|
||||||
if otherPerc > 0 {
|
if otherPerc > 0 {
|
||||||
langPerc["other"] = otherPerc
|
langPerc["other"] = otherPerc
|
||||||
}
|
}
|
||||||
|
roundByLargestRemainder(langPerc, 100)
|
||||||
return langPerc
|
return langPerc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rounds to 1 decimal point, target should be the expected sum of percs
|
||||||
|
func roundByLargestRemainder(percs map[string]float32, target float32) {
|
||||||
|
leftToDistribute := int(target * 10)
|
||||||
|
|
||||||
|
keys := make([]string, 0, len(percs))
|
||||||
|
|
||||||
|
for k, v := range percs {
|
||||||
|
percs[k] = v * 10
|
||||||
|
floored := math.Floor(float64(percs[k]))
|
||||||
|
leftToDistribute -= int(floored)
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the keys by the largest remainder
|
||||||
|
sort.SliceStable(keys, func(i, j int) bool {
|
||||||
|
_, remainderI := math.Modf(float64(percs[keys[i]]))
|
||||||
|
_, remainderJ := math.Modf(float64(percs[keys[j]]))
|
||||||
|
return remainderI > remainderJ
|
||||||
|
})
|
||||||
|
|
||||||
|
// Increment the values in order of largest remainder
|
||||||
|
for _, k := range keys {
|
||||||
|
percs[k] = float32(math.Floor(float64(percs[k])))
|
||||||
|
if leftToDistribute > 0 {
|
||||||
|
percs[k]++
|
||||||
|
leftToDistribute--
|
||||||
|
}
|
||||||
|
percs[k] /= 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GetLanguageStats returns the language statistics for a repository
|
// GetLanguageStats returns the language statistics for a repository
|
||||||
func GetLanguageStats(ctx context.Context, repo *Repository) (LanguageStatList, error) {
|
func GetLanguageStats(ctx context.Context, repo *Repository) (LanguageStatList, error) {
|
||||||
stats := make(LanguageStatList, 0, 6)
|
stats := make(LanguageStatList, 0, 6)
|
||||||
|
|
Loading…
Reference in New Issue