fix: исправлен расчет общего процента выполнения в ежедневном отчете и унифицирована логика
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 46s

This commit is contained in:
poignatov
2026-01-03 16:13:28 +03:00
parent 4767f5975c
commit 2b9a024d3e
2 changed files with 78 additions and 143 deletions

View File

@@ -1 +1 @@
2.8.5
2.8.6

View File

@@ -2234,49 +2234,8 @@ func (a *App) getWeeklyStatsHandler(w http.ResponseWriter, r *http.Request) {
projects = append(projects, project)
}
// Находим среднее внутри каждой группы
groupAverages := make([]float64, 0)
for priorityVal, scores := range groups {
if len(scores) > 0 {
var avg float64
// Для приоритета 1 и 2 - обычное среднее (как было)
if priorityVal == 1 || priorityVal == 2 {
sum := 0.0
for _, score := range scores {
sum += score
}
avg = sum / float64(len(scores))
} else {
// Для проектов без приоритета (priorityVal == 0) - новая формула
projectCount := float64(len(scores))
multiplier := 100.0 / (projectCount * 0.8)
sum := 0.0
for _, score := range scores {
// score уже в процентах (например, 80.0), переводим в долю (0.8)
scoreAsDecimal := score / 100.0
sum += scoreAsDecimal * multiplier
}
avg = math.Min(120.0, sum)
}
groupAverages = append(groupAverages, avg)
}
}
// Находим среднее между всеми группами
var total *float64
if len(groupAverages) > 0 {
sum := 0.0
for _, avg := range groupAverages {
sum += avg
}
overallProgress := sum / float64(len(groupAverages))
overallProgressRounded := roundToFourDecimals(overallProgress)
total = &overallProgressRounded
}
// Вычисляем общий процент выполнения
total := calculateOverallProgress(groups)
response := WeeklyStatsResponse{
Total: total,
@@ -3034,49 +2993,8 @@ func (a *App) getWeeklyStatsData() (*WeeklyStatsResponse, error) {
projects = append(projects, project)
}
// Находим среднее внутри каждой группы
groupAverages := make([]float64, 0)
for priorityVal, scores := range groups {
if len(scores) > 0 {
var avg float64
// Для приоритета 1 и 2 - обычное среднее (как было)
if priorityVal == 1 || priorityVal == 2 {
sum := 0.0
for _, score := range scores {
sum += score
}
avg = sum / float64(len(scores))
} else {
// Для проектов без приоритета (priorityVal == 0) - новая формула
projectCount := float64(len(scores))
multiplier := 100.0 / (projectCount * 0.8)
sum := 0.0
for _, score := range scores {
// score уже в процентах (например, 80.0), переводим в долю (0.8)
scoreAsDecimal := score / 100.0
sum += scoreAsDecimal * multiplier
}
avg = math.Min(120.0, sum)
}
groupAverages = append(groupAverages, avg)
}
}
// Находим среднее между всеми группами
var total *float64
if len(groupAverages) > 0 {
sum := 0.0
for _, avg := range groupAverages {
sum += avg
}
overallProgress := sum / float64(len(groupAverages))
overallProgressRounded := roundToFourDecimals(overallProgress)
total = &overallProgressRounded
}
// Вычисляем общий процент выполнения
total := calculateOverallProgress(groups)
response := WeeklyStatsResponse{
Total: total,
@@ -3169,6 +3087,7 @@ func (a *App) getWeeklyStatsDataForUser(userID int) (*WeeklyStatsResponse, error
maxGoalScoreVal = *project.MaxGoalScore
}
// Параметры бонуса в зависимости от priority
var extraBonusLimit float64 = 20
if priorityVal == 1 {
extraBonusLimit = 50
@@ -3176,71 +3095,36 @@ func (a *App) getWeeklyStatsDataForUser(userID int) (*WeeklyStatsResponse, error
extraBonusLimit = 35
}
var calculatedScore float64
// Расчет базового прогресса
var baseProgress float64
if minGoalScoreVal > 0 {
percentage := (totalScore / minGoalScoreVal) * 100.0
if maxGoalScoreVal > 0 {
if totalScore >= maxGoalScoreVal {
calculatedScore = 100.0 + math.Min(extraBonusLimit, ((totalScore-maxGoalScoreVal)/maxGoalScoreVal)*100.0)
} else {
calculatedScore = percentage
}
} else {
calculatedScore = math.Min(100.0+extraBonusLimit, percentage)
}
} else {
calculatedScore = 0.0
baseProgress = (min(totalScore, minGoalScoreVal) / minGoalScoreVal) * 100.0
}
project.CalculatedScore = roundToFourDecimals(calculatedScore)
// Расчет экстра прогресса
var extraProgress float64
denominator := maxGoalScoreVal - minGoalScoreVal
if denominator > 0 && totalScore > minGoalScoreVal {
excess := min(totalScore, maxGoalScoreVal) - minGoalScoreVal
extraProgress = (excess / denominator) * extraBonusLimit
}
resultScore := baseProgress + extraProgress
project.CalculatedScore = roundToTwoDecimals(resultScore)
projects = append(projects, project)
if priorityVal > 0 {
groups[priorityVal] = append(groups[priorityVal], project.CalculatedScore)
} else {
groups[0] = append(groups[0], project.CalculatedScore)
}
}
// Расчет средних по группам
groupAverages := make([]float64, 0)
for priorityVal, scores := range groups {
if len(scores) > 0 {
var avg float64
if priorityVal == 1 || priorityVal == 2 {
sum := 0.0
for _, score := range scores {
sum += score
}
avg = sum / float64(len(scores))
} else {
projectCount := float64(len(scores))
multiplier := 100.0 / (projectCount * 0.8)
sum := 0.0
for _, score := range scores {
scoreAsDecimal := score / 100.0
sum += scoreAsDecimal * multiplier
}
avg = math.Min(120.0, sum)
// Группировка для итогового расчета
// Проекты с minGoal = 0 или null не учитываются в общем проценте выполнения
if minGoalScoreVal > 0 {
if _, exists := groups[priorityVal]; !exists {
groups[priorityVal] = make([]float64, 0)
}
groupAverages = append(groupAverages, avg)
groups[priorityVal] = append(groups[priorityVal], project.CalculatedScore)
}
}
var total *float64
if len(groupAverages) > 0 {
sum := 0.0
for _, avg := range groupAverages {
sum += avg
}
overallProgress := sum / float64(len(groupAverages))
overallProgressRounded := roundToFourDecimals(overallProgress)
total = &overallProgressRounded
}
// Вычисляем общий процент выполнения
total := calculateOverallProgress(groups)
response := WeeklyStatsResponse{
Total: total,
@@ -3681,6 +3565,57 @@ func roundToFourDecimals(val float64) float64 {
return float64(int(val*10000+0.5)) / 10000.0
}
// calculateOverallProgress вычисляет общий процент выполнения на основе групп проектов по приоритетам
// groups - карта приоритетов к спискам calculatedScore проектов
// Возвращает указатель на float64 с общим процентом выполнения или nil, если нет данных
func calculateOverallProgress(groups map[int][]float64) *float64 {
// Находим среднее внутри каждой группы
groupAverages := make([]float64, 0)
for priorityVal, scores := range groups {
if len(scores) > 0 {
var avg float64
// Для приоритета 1 и 2 - обычное среднее (как было)
if priorityVal == 1 || priorityVal == 2 {
sum := 0.0
for _, score := range scores {
sum += score
}
avg = sum / float64(len(scores))
} else {
// Для проектов без приоритета (priorityVal == 0) - новая формула
projectCount := float64(len(scores))
multiplier := 100.0 / (projectCount * 0.8)
sum := 0.0
for _, score := range scores {
// score уже в процентах (например, 80.0), переводим в долю (0.8)
scoreAsDecimal := score / 100.0
sum += scoreAsDecimal * multiplier
}
avg = math.Min(120.0, sum)
}
groupAverages = append(groupAverages, avg)
}
}
// Находим среднее между всеми группами
var total *float64
if len(groupAverages) > 0 {
sum := 0.0
for _, avg := range groupAverages {
sum += avg
}
overallProgress := sum / float64(len(groupAverages))
overallProgressRounded := roundToFourDecimals(overallProgress)
total = &overallProgressRounded
}
return total
}
// TelegramIntegration представляет запись из таблицы telegram_integrations
type TelegramIntegration struct {
ID int `json:"id"`