From 4e270cb322e8a8b279dfa721daffa1d3f2fc93cb Mon Sep 17 00:00:00 2001 From: poignatov Date: Thu, 29 Jan 2026 15:54:04 +0300 Subject: [PATCH] =?UTF-8?q?4.2.1:=20=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D1=81=D0=BE=D1=80=D1=82=D0=B8=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=B6=D0=B5=D0=BB=D0=B0=D0=BD=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VERSION | 2 +- play-life-backend/main.go | 88 ++++++++++++++++++++++---------------- play-life-web/package.json | 2 +- 3 files changed, 53 insertions(+), 39 deletions(-) diff --git a/VERSION b/VERSION index 6aba2b2..fae6e3d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.2.0 +4.2.1 diff --git a/play-life-backend/main.go b/play-life-backend/main.go index 99f4d9d..af2b457 100644 --- a/play-life-backend/main.go +++ b/play-life-backend/main.go @@ -11900,6 +11900,26 @@ func (a *App) getBoardItemsHandler(w http.ResponseWriter, r *http.Request) { } } + // Сортируем unlocked по возрастанию суммы баллов (от меньшего к большему) + sort.Slice(unlocked, func(i, j int) bool { + valueI := calculateUnlockedSortValue(unlocked[i]) + valueJ := calculateUnlockedSortValue(unlocked[j]) + if valueI == valueJ { + return unlocked[i].ID < unlocked[j].ID + } + return valueI < valueJ + }) + + // Сортируем locked по возрастанию суммы оставшихся баллов (от меньшего к большему) + sort.Slice(locked, func(i, j int) bool { + valueI := calculateLockedSortValue(locked[i]) + valueJ := calculateLockedSortValue(locked[j]) + if valueI == valueJ { + return locked[i].ID < locked[j].ID + } + return valueI < valueJ + }) + // Считаем завершённые var completedCount int a.DB.QueryRow(`SELECT COUNT(*) FROM wishlist_items WHERE board_id = $1 AND completed = TRUE AND deleted = FALSE`, @@ -12130,24 +12150,32 @@ func (a *App) getBoardCompletedHandler(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(completed) } -// getWishlistItemsByBoard загружает желания конкретной доски -// calculateUnlockValue вычисляет значение для сортировки желаний -// Возвращает значение, где: -// - Отрицательные значения: unlocked элементы (ставим в начало) -// - Положительные значения: сумма оставшихся баллов для locked элементов (меньше = выше в списке) -func calculateUnlockValue(item WishlistItem) float64 { - // Если элемент уже unlocked, ставим его в начало (отрицательное значение) - if item.Unlocked { - return -1.0 - } - - // Суммируем оставшиеся баллы по всем условиям project_points - var totalRemaining float64 = 0.0 - var hasProjectPointsConditions bool = false - +// calculateUnlockedSortValue считает сумму баллов, которые были нужны для разблокировки +// Задача считается как 1 балл, project_points как required_points +func calculateUnlockedSortValue(item WishlistItem) float64 { + var totalRequired float64 = 0.0 for _, condition := range item.UnlockConditions { - if condition.Type == "project_points" { - hasProjectPointsConditions = true + if condition.Type == "task_completion" { + totalRequired += 1.0 + } else if condition.Type == "project_points" { + if condition.RequiredPoints != nil { + totalRequired += *condition.RequiredPoints + } + } + } + return totalRequired +} + +// calculateLockedSortValue считает сумму оставшихся баллов для разблокировки +// Задача считается как 1 балл (если не выполнена), project_points как remaining баллы +func calculateLockedSortValue(item WishlistItem) float64 { + var totalRemaining float64 = 0.0 + for _, condition := range item.UnlockConditions { + if condition.Type == "task_completion" { + if condition.TaskCompleted == nil || !*condition.TaskCompleted { + totalRemaining += 1.0 + } + } else if condition.Type == "project_points" { if condition.CurrentPoints != nil && condition.RequiredPoints != nil { remaining := *condition.RequiredPoints - *condition.CurrentPoints if remaining > 0 { @@ -12156,16 +12184,15 @@ func calculateUnlockValue(item WishlistItem) float64 { } } } - - // Если есть условия project_points, возвращаем сумму оставшихся баллов - if hasProjectPointsConditions { - return totalRemaining + // Если нет условий или все условия выполнены, ставим в конец + if totalRemaining == 0.0 && len(item.UnlockConditions) > 0 { + return 999999.0 } - - // Элементы без условий project_points ставим в конец (большое значение) - return 999999.0 + return totalRemaining } +// getWishlistItemsByBoard загружает желания конкретной доски + func (a *App) getWishlistItemsByBoard(boardID int, userID int) ([]WishlistItem, error) { query := ` SELECT @@ -12341,19 +12368,6 @@ func (a *App) getWishlistItemsByBoard(boardID int, userID int) ([]WishlistItem, items = append(items, *item) } - // Сортируем: сначала unlocked, затем по сумме оставшихся баллов (от меньшего к большему) - sort.Slice(items, func(i, j int) bool { - valueI := calculateUnlockValue(items[i]) - valueJ := calculateUnlockValue(items[j]) - - // Если значения равны, сортируем по ID для стабильного порядка - if valueI == valueJ { - return items[i].ID < items[j].ID - } - - return valueI < valueJ - }) - return items, nil } diff --git a/play-life-web/package.json b/play-life-web/package.json index a2f0730..90b833d 100644 --- a/play-life-web/package.json +++ b/play-life-web/package.json @@ -1,6 +1,6 @@ { "name": "play-life-web", - "version": "4.2.0", + "version": "4.2.1", "type": "module", "scripts": { "dev": "vite",