diff --git a/VERSION b/VERSION index 766d708..e43686a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.8.5 +2.8.6 diff --git a/play-life-backend/main.go b/play-life-backend/main.go index 6b5e83d..10cfc68 100644 --- a/play-life-backend/main.go +++ b/play-life-backend/main.go @@ -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"`