diff --git a/VERSION b/VERSION index 703e89e..b0880dd 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.25.3 +3.25.4 diff --git a/play-life-backend/main.go b/play-life-backend/main.go index 0b44201..7e5f427 100644 --- a/play-life-backend/main.go +++ b/play-life-backend/main.go @@ -108,9 +108,18 @@ type WeeklyProjectStats struct { CalculatedScore float64 `json:"calculated_score"` } +type GroupsProgress struct { + Group1 *float64 `json:"group1,omitempty"` + Group2 *float64 `json:"group2,omitempty"` + Group0 *float64 `json:"group0,omitempty"` +} + type WeeklyStatsResponse struct { - Total *float64 `json:"total,omitempty"` - Projects []WeeklyProjectStats `json:"projects"` + Total *float64 `json:"total,omitempty"` + GroupProgress1 *float64 `json:"group_progress_1,omitempty"` + GroupProgress2 *float64 `json:"group_progress_2,omitempty"` + GroupProgress0 *float64 `json:"group_progress_0,omitempty"` + Projects []WeeklyProjectStats `json:"projects"` } type MessagePostRequest struct { @@ -2538,12 +2547,18 @@ func (a *App) getWeeklyStatsHandler(w http.ResponseWriter, r *http.Request) { projects = append(projects, project) } + // Вычисляем проценты для каждой группы + groupsProgress := calculateGroupsProgress(groups) + // Вычисляем общий процент выполнения - total := calculateOverallProgress(groups) + total := calculateOverallProgress(groupsProgress) response := WeeklyStatsResponse{ - Total: total, - Projects: projects, + Total: total, + GroupProgress1: groupsProgress.Group1, + GroupProgress2: groupsProgress.Group2, + GroupProgress0: groupsProgress.Group0, + Projects: projects, } w.Header().Set("Content-Type", "application/json") @@ -3727,12 +3742,18 @@ func (a *App) getWeeklyStatsData() (*WeeklyStatsResponse, error) { projects = append(projects, project) } + // Вычисляем проценты для каждой группы + groupsProgress := calculateGroupsProgress(groups) + // Вычисляем общий процент выполнения - total := calculateOverallProgress(groups) + total := calculateOverallProgress(groupsProgress) response := WeeklyStatsResponse{ - Total: total, - Projects: projects, + Total: total, + GroupProgress1: groupsProgress.Group1, + GroupProgress2: groupsProgress.Group2, + GroupProgress0: groupsProgress.Group0, + Projects: projects, } return &response, nil @@ -3857,12 +3878,18 @@ func (a *App) getWeeklyStatsDataForUser(userID int) (*WeeklyStatsResponse, error } } + // Вычисляем проценты для каждой группы + groupsProgress := calculateGroupsProgress(groups) + // Вычисляем общий процент выполнения - total := calculateOverallProgress(groups) + total := calculateOverallProgress(groupsProgress) response := WeeklyStatsResponse{ - Total: total, - Projects: projects, + Total: total, + GroupProgress1: groupsProgress.Group1, + GroupProgress2: groupsProgress.Group2, + GroupProgress0: groupsProgress.Group0, + Projects: projects, } return &response, nil @@ -4386,16 +4413,16 @@ func roundToFourDecimals(val float64) float64 { return float64(int(val*10000+0.5)) / 10000.0 } -// calculateOverallProgress вычисляет общий процент выполнения на основе групп проектов по приоритетам +// calculateGroupsProgress вычисляет проценты выполнения для каждой группы приоритетов // groups - карта приоритетов к спискам calculatedScore проектов -// Возвращает указатель на float64 с общим процентом выполнения или nil, если нет данных +// Возвращает структуру GroupsProgress с процентами для каждой группы // Если какая-то группа отсутствует, она считается как 100% -func calculateOverallProgress(groups map[int][]float64) *float64 { +func calculateGroupsProgress(groups map[int][]float64) GroupsProgress { // Всего есть 3 группы: приоритет 1, приоритет 2, приоритет 0 // Вычисляем среднее для каждой группы, если она есть // Если группы нет, считаем её как 100% - groupAverages := make(map[int]float64) + result := GroupsProgress{} // Обрабатываем все 3 возможных приоритета priorities := []int{1, 2, 0} @@ -4403,13 +4430,12 @@ func calculateOverallProgress(groups map[int][]float64) *float64 { for _, priorityVal := range priorities { scores, exists := groups[priorityVal] + var avg float64 if !exists || len(scores) == 0 { // Если группы нет, считаем как 100% - groupAverages[priorityVal] = 100.0 + avg = 100.0 } else { // Вычисляем среднее для группы - var avg float64 - // Для приоритета 1 и 2 - обычное среднее if priorityVal == 1 || priorityVal == 2 { sum := 0.0 @@ -4431,18 +4457,52 @@ func calculateOverallProgress(groups map[int][]float64) *float64 { avg = math.Min(120.0, sum) } - - groupAverages[priorityVal] = avg + } + + // Сохраняем результат в соответствующее поле + avgRounded := roundToFourDecimals(avg) + switch priorityVal { + case 1: + result.Group1 = &avgRounded + case 2: + result.Group2 = &avgRounded + case 0: + result.Group0 = &avgRounded } } + return result +} + +// calculateOverallProgress вычисляет общий процент выполнения на основе процентов групп +// groupsProgress - структура с процентами для каждой группы приоритетов +// Возвращает указатель на float64 с общим процентом выполнения +// Всегда вычисляет среднее всех трех групп (даже если какая-то группа отсутствует, она считается как 100%) +func calculateOverallProgress(groupsProgress GroupsProgress) *float64 { // Находим среднее между всеми тремя группами - sum := 0.0 - for _, priorityVal := range priorities { - sum += groupAverages[priorityVal] + // Если какая-то группа отсутствует (nil), считаем её как 100% + + var group1Val, group2Val, group0Val float64 + + if groupsProgress.Group1 != nil { + group1Val = *groupsProgress.Group1 + } else { + group1Val = 100.0 } - overallProgress := sum / 3.0 // Всегда делим на 3, так как групп всегда 3 + if groupsProgress.Group2 != nil { + group2Val = *groupsProgress.Group2 + } else { + group2Val = 100.0 + } + + if groupsProgress.Group0 != nil { + group0Val = *groupsProgress.Group0 + } else { + group0Val = 100.0 + } + + overallProgress := (group1Val + group2Val + group0Val) / 3.0 // Всегда делим на 3, так как групп всегда 3 overallProgressRounded := roundToFourDecimals(overallProgress) total := &overallProgressRounded diff --git a/play-life-web/package.json b/play-life-web/package.json index d9e52d9..f3886ef 100644 --- a/play-life-web/package.json +++ b/play-life-web/package.json @@ -1,6 +1,6 @@ { "name": "play-life-web", - "version": "3.25.3", + "version": "3.25.4", "type": "module", "scripts": { "dev": "vite", diff --git a/play-life-web/src/App.jsx b/play-life-web/src/App.jsx index 05f4526..6999b5e 100644 --- a/play-life-web/src/App.jsx +++ b/play-life-web/src/App.jsx @@ -307,6 +307,9 @@ function AppContent() { // Обрабатываем ответ: приходит массив с одним объектом [{total: ..., projects: [...]}] let projects = [] let total = null + let groupProgress1 = null + let groupProgress2 = null + let groupProgress0 = null if (Array.isArray(jsonData) && jsonData.length > 0) { // Если ответ - массив, проверяем первый элемент @@ -316,6 +319,9 @@ function AppContent() { if (firstItem.projects && Array.isArray(firstItem.projects)) { projects = firstItem.projects total = firstItem.total !== undefined ? firstItem.total : null + groupProgress1 = firstItem.group_progress_1 !== undefined ? firstItem.group_progress_1 : null + groupProgress2 = firstItem.group_progress_2 !== undefined ? firstItem.group_progress_2 : null + groupProgress0 = firstItem.group_progress_0 !== undefined ? firstItem.group_progress_0 : null } else { // Если это просто массив проектов projects = jsonData @@ -328,11 +334,17 @@ function AppContent() { // Если ответ - объект напрямую projects = jsonData.projects || jsonData.data || [] total = jsonData.total !== undefined ? jsonData.total : null + groupProgress1 = jsonData.group_progress_1 !== undefined ? jsonData.group_progress_1 : null + groupProgress2 = jsonData.group_progress_2 !== undefined ? jsonData.group_progress_2 : null + groupProgress0 = jsonData.group_progress_0 !== undefined ? jsonData.group_progress_0 : null } setCurrentWeekData({ projects: Array.isArray(projects) ? projects : [], - total: total + total: total, + group_progress_1: groupProgress1, + group_progress_2: groupProgress2, + group_progress_0: groupProgress0 }) } catch (err) { setCurrentWeekError(err.message) diff --git a/play-life-web/src/components/CurrentWeek.jsx b/play-life-web/src/components/CurrentWeek.jsx index 0b4b6ee..a5d306f 100644 --- a/play-life-web/src/components/CurrentWeek.jsx +++ b/play-life-web/src/components/CurrentWeek.jsx @@ -356,46 +356,27 @@ function CurrentWeek({ onProjectClick, data, loading, error, onRetry, allProject }) } - // Вычисляем процент выполнения для каждой группы - const calculateGroupProgress = (projects) => { - if (projects.length === 0) return 0 - - let totalProgress = 0 - let validProjects = 0 - - projects.forEach(project => { - const safeTotal = Number.isFinite(project.total_score) ? project.total_score : 0 - const safeMinGoal = Number.isFinite(project.min_goal_score) ? project.min_goal_score : 0 - - if (safeMinGoal > 0) { - const projectProgress = Math.min((safeTotal / safeMinGoal) * 100, 100) - totalProgress += projectProgress - validProjects++ - } - }) - - return validProjects > 0 ? totalProgress / validProjects : 0 - } - - const mainProgress = calculateGroupProgress(priorityGroups.main) - const importantProgress = calculateGroupProgress(priorityGroups.important) - const othersProgress = calculateGroupProgress(priorityGroups.others) - - // Пересчитываем общий прогресс как среднее от групповых процентов - const recalculatedOverallProgress = (() => { - const groups = [] - if (priorityGroups.main.length > 0) groups.push(mainProgress) - if (priorityGroups.important.length > 0) groups.push(importantProgress) - if (priorityGroups.others.length > 0) groups.push(othersProgress) - - if (groups.length === 0) return null - - const average = groups.reduce((sum, progress) => sum + progress, 0) / groups.length - return Math.max(0, average) // Убираем ограничение на 100% для текста + // Получаем проценты групп из API данных + const mainProgress = (() => { + const rawValue = data?.group_progress_1 + const parsedValue = rawValue === undefined || rawValue === null ? null : parseFloat(rawValue) + return Number.isFinite(parsedValue) && parsedValue >= 0 ? parsedValue : 0 })() - // Используем пересчитанный общий прогресс вместо API данных - const displayOverallProgress = recalculatedOverallProgress !== null ? recalculatedOverallProgress : (hasProgressData ? overallProgress : null) + const importantProgress = (() => { + const rawValue = data?.group_progress_2 + const parsedValue = rawValue === undefined || rawValue === null ? null : parseFloat(rawValue) + return Number.isFinite(parsedValue) && parsedValue >= 0 ? parsedValue : 0 + })() + + const othersProgress = (() => { + const rawValue = data?.group_progress_0 + const parsedValue = rawValue === undefined || rawValue === null ? null : parseFloat(rawValue) + return Number.isFinite(parsedValue) && parsedValue >= 0 ? parsedValue : 0 + })() + + // Используем общий прогресс из API данных + const displayOverallProgress = overallProgress return (