From 6618966ebc339ccbb90f3a559c90a66fd64bb887 Mon Sep 17 00:00:00 2001 From: pa Date: Thu, 19 Mar 2026 18:40:51 +0900 Subject: [PATCH] feat: add "Most Visited Worlds" section to Activity tab --- .../dialogs/UserDialog/UserDialog.vue | 44 ++-- .../UserDialog/UserDialogActivityTab.vue | 235 ++++++++++++++++-- src/localization/en.json | 3 + src/services/database/gameLog.js | 45 +++- 4 files changed, 290 insertions(+), 37 deletions(-) diff --git a/src/components/dialogs/UserDialog/UserDialog.vue b/src/components/dialogs/UserDialog/UserDialog.vue index 0561430a..09ca8d99 100644 --- a/src/components/dialogs/UserDialog/UserDialog.vue +++ b/src/components/dialogs/UserDialog/UserDialog.vue @@ -42,7 +42,7 @@ - diff --git a/src/localization/en.json b/src/localization/en.json index ce18f71f..2c492fe7 100644 --- a/src/localization/en.json +++ b/src/localization/en.json @@ -1455,6 +1455,9 @@ "exclude_hours": "Exclude hours", "no_data": "Not enough data to calculate overlap", "times_overlap": "times overlapping" + }, + "most_visited_worlds": { + "header": "Most Visited Worlds" } }, "note_memo": { diff --git a/src/services/database/gameLog.js b/src/services/database/gameLog.js index 03a4ddf0..35cee3a8 100644 --- a/src/services/database/gameLog.js +++ b/src/services/database/gameLog.js @@ -1380,13 +1380,52 @@ const gameLog = { */ async getCurrentUserOnlineSessions() { const data = []; + await sqliteService.execute((dbRow) => { + data.push({ created_at: dbRow[0], time: dbRow[1] || 0 }); + }, `SELECT created_at, time FROM gamelog_location ORDER BY created_at`); + return data; + }, + + /** + * Get current user's top visited worlds from gamelog_location. + * Groups by world_id and aggregates visit count and total time. + * @param {number} [days] - Number of days to look back. Omit or 0 for all time. + * @param {number} [limit=5] - Maximum number of worlds to return. + * @returns {Promise>} + */ + async getMyTopWorlds(days = 0, limit = 5) { + const results = []; + const whereClause = + days > 0 ? `AND created_at >= datetime('now', @daysOffset)` : ''; + const params = { '@limit': limit }; + if (days > 0) { + params['@daysOffset'] = `-${days} days`; + } await sqliteService.execute( (dbRow) => { - data.push({ created_at: dbRow[0], time: dbRow[1] || 0 }); + results.push({ + worldId: dbRow[0], + worldName: dbRow[1] || dbRow[0], + visitCount: dbRow[2], + totalTime: dbRow[3] || 0 + }); }, - `SELECT created_at, time FROM gamelog_location ORDER BY created_at` + `SELECT + world_id, + world_name, + COUNT(*) AS visit_count, + SUM(time) AS total_time + FROM gamelog_location + WHERE world_id IS NOT NULL + AND world_id != '' + AND world_id LIKE 'wrld_%' + ${whereClause} + GROUP BY world_id + ORDER BY total_time DESC + LIMIT @limit`, + params ); - return data; + return results; }, async getUserIdFromDisplayName(displayName) {