mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-05-04 22:06:06 +02:00
refactor top worlds
This commit is contained in:
@@ -28,10 +28,6 @@ function bucketCacheTable() {
|
||||
return `${dbVars.userPrefix}_activity_bucket_cache_v2`;
|
||||
}
|
||||
|
||||
function topWorldsCacheTable() {
|
||||
return `${dbVars.userPrefix}_activity_top_worlds_cache_v2`;
|
||||
}
|
||||
|
||||
function parseJson(value, fallback) {
|
||||
if (!value) {
|
||||
return fallback;
|
||||
@@ -52,16 +48,24 @@ const activityV2 = {
|
||||
ACTIVITY_RANGE_CACHE_KIND,
|
||||
|
||||
async getActivitySourceSliceV2({ userId, isSelf, fromDays, toDays = 0 }) {
|
||||
const fromDateIso = new Date(Date.now() - fromDays * 86400000).toISOString();
|
||||
const toDateIso = toDays > 0
|
||||
? new Date(Date.now() - toDays * 86400000).toISOString()
|
||||
: '';
|
||||
const fromDateIso = new Date(
|
||||
Date.now() - fromDays * 86400000
|
||||
).toISOString();
|
||||
const toDateIso =
|
||||
toDays > 0
|
||||
? new Date(Date.now() - toDays * 86400000).toISOString()
|
||||
: '';
|
||||
return isSelf
|
||||
? this.getCurrentUserLocationSliceV2(fromDateIso, toDateIso)
|
||||
: this.getFriendPresenceSliceV2(userId, fromDateIso, toDateIso);
|
||||
},
|
||||
|
||||
async getActivitySourceAfterV2({ userId, isSelf, afterCreatedAt, inclusive = false }) {
|
||||
async getActivitySourceAfterV2({
|
||||
userId,
|
||||
isSelf,
|
||||
afterCreatedAt,
|
||||
inclusive = false
|
||||
}) {
|
||||
return isSelf
|
||||
? this.getCurrentUserLocationAfterV2(afterCreatedAt, inclusive)
|
||||
: this.getFriendPresenceAfterV2(userId, afterCreatedAt);
|
||||
@@ -122,7 +126,9 @@ const activityV2 = {
|
||||
);
|
||||
}
|
||||
|
||||
return rows.sort((left, right) => left.created_at.localeCompare(right.created_at));
|
||||
return rows.sort((left, right) =>
|
||||
left.created_at.localeCompare(right.created_at)
|
||||
);
|
||||
},
|
||||
|
||||
async getFriendPresenceAfterV2(userId, afterCreatedAt) {
|
||||
@@ -167,8 +173,9 @@ const activityV2 = {
|
||||
FROM gamelog_location
|
||||
WHERE created_at >= @fromDateIso
|
||||
${toDateIso ? 'AND created_at < @toDateIso' : ''}
|
||||
${toDateIso
|
||||
? `UNION ALL
|
||||
${
|
||||
toDateIso
|
||||
? `UNION ALL
|
||||
SELECT created_at, time, 2 AS sort_group
|
||||
FROM (
|
||||
SELECT created_at, time
|
||||
@@ -177,7 +184,8 @@ const activityV2 = {
|
||||
ORDER BY created_at
|
||||
LIMIT 1
|
||||
)`
|
||||
: ''}
|
||||
: ''
|
||||
}
|
||||
)
|
||||
ORDER BY created_at ASC, sort_group ASC
|
||||
`,
|
||||
@@ -214,7 +222,8 @@ const activityV2 = {
|
||||
updatedAt: dbRow[1] || '',
|
||||
isSelf: Boolean(dbRow[2]),
|
||||
sourceLastCreatedAt: dbRow[3] || '',
|
||||
pendingSessionStartAt: typeof dbRow[4] === 'number' ? dbRow[4] : null,
|
||||
pendingSessionStartAt:
|
||||
typeof dbRow[4] === 'number' ? dbRow[4] : null,
|
||||
cachedRangeDays: dbRow[5] || 0
|
||||
};
|
||||
},
|
||||
@@ -277,7 +286,11 @@ const activityV2 = {
|
||||
}
|
||||
},
|
||||
|
||||
async appendActivitySessionsV2({ userId, sessions = [], replaceFromStartAt = null }) {
|
||||
async appendActivitySessionsV2({
|
||||
userId,
|
||||
sessions = [],
|
||||
replaceFromStartAt = null
|
||||
}) {
|
||||
await sqliteService.executeNonQuery('BEGIN');
|
||||
try {
|
||||
if (replaceFromStartAt !== null) {
|
||||
@@ -391,86 +404,15 @@ const activityV2 = {
|
||||
'@bucketVersion': entry.bucketVersion || 1,
|
||||
'@builtFromCursor': entry.builtFromCursor || '',
|
||||
'@rawBucketsJson': JSON.stringify(entry.rawBuckets || []),
|
||||
'@normalizedBucketsJson': JSON.stringify(entry.normalizedBuckets || []),
|
||||
'@normalizedBucketsJson': JSON.stringify(
|
||||
entry.normalizedBuckets || []
|
||||
),
|
||||
'@summaryJson': JSON.stringify(entry.summary || {}),
|
||||
'@builtAt': entry.builtAt || ''
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
async getActivityTopWorldsCacheV2(userId, rangeDays) {
|
||||
const worlds = [];
|
||||
let builtFromCursor = '';
|
||||
let builtAt = '';
|
||||
await sqliteService.execute(
|
||||
(dbRow) => {
|
||||
builtFromCursor = dbRow[0] || builtFromCursor;
|
||||
builtAt = dbRow[1] || builtAt;
|
||||
worlds.push({
|
||||
worldId: dbRow[3],
|
||||
worldName: dbRow[4],
|
||||
visitCount: dbRow[5] || 0,
|
||||
totalTime: dbRow[6] || 0
|
||||
});
|
||||
},
|
||||
`SELECT built_from_cursor, built_at, rank_index, world_id, world_name, visit_count, total_time
|
||||
FROM ${topWorldsCacheTable()}
|
||||
WHERE user_id = @userId AND range_days = @rangeDays
|
||||
ORDER BY rank_index`,
|
||||
{
|
||||
'@userId': userId,
|
||||
'@rangeDays': rangeDays
|
||||
}
|
||||
);
|
||||
if (worlds.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
userId,
|
||||
rangeDays,
|
||||
builtFromCursor,
|
||||
builtAt,
|
||||
worlds
|
||||
};
|
||||
},
|
||||
|
||||
async replaceActivityTopWorldsCacheV2(entry) {
|
||||
await sqliteService.executeNonQuery('BEGIN');
|
||||
try {
|
||||
await sqliteService.executeNonQuery(
|
||||
`DELETE FROM ${topWorldsCacheTable()} WHERE user_id = @userId AND range_days = @rangeDays`,
|
||||
{
|
||||
'@userId': entry.userId,
|
||||
'@rangeDays': entry.rangeDays
|
||||
}
|
||||
);
|
||||
|
||||
for (let index = 0; index < entry.worlds.length; index++) {
|
||||
const world = entry.worlds[index];
|
||||
await sqliteService.executeNonQuery(
|
||||
`INSERT OR REPLACE INTO ${topWorldsCacheTable()}
|
||||
(user_id, range_days, rank_index, world_id, world_name, visit_count, total_time, built_from_cursor, built_at)
|
||||
VALUES (@userId, @rangeDays, @rankIndex, @worldId, @worldName, @visitCount, @totalTime, @builtFromCursor, @builtAt)`,
|
||||
{
|
||||
'@userId': entry.userId,
|
||||
'@rangeDays': entry.rangeDays,
|
||||
'@rankIndex': index,
|
||||
'@worldId': world.worldId,
|
||||
'@worldName': world.worldName || world.worldId,
|
||||
'@visitCount': world.visitCount || 0,
|
||||
'@totalTime': world.totalTime || 0,
|
||||
'@builtFromCursor': entry.builtFromCursor || '',
|
||||
'@builtAt': entry.builtAt || ''
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
await sqliteService.executeNonQuery('COMMIT');
|
||||
} catch (error) {
|
||||
await sqliteService.executeNonQuery('ROLLBACK');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
async function insertSessions(userId, sessions = []) {
|
||||
@@ -479,7 +421,11 @@ async function insertSessions(userId, sessions = []) {
|
||||
}
|
||||
|
||||
const chunkSize = 250;
|
||||
for (let chunkStart = 0; chunkStart < sessions.length; chunkStart += chunkSize) {
|
||||
for (
|
||||
let chunkStart = 0;
|
||||
chunkStart < sessions.length;
|
||||
chunkStart += chunkSize
|
||||
) {
|
||||
const chunk = sessions.slice(chunkStart, chunkStart + chunkSize);
|
||||
const args = {};
|
||||
const values = chunk.map((session, index) => {
|
||||
|
||||
@@ -1390,7 +1390,9 @@ const gameLog = {
|
||||
const where = [];
|
||||
|
||||
if (fromDays > 0) {
|
||||
const fromDate = new Date(now.getTime() - fromDays * 86400000).toISOString();
|
||||
const fromDate = new Date(
|
||||
now.getTime() - fromDays * 86400000
|
||||
).toISOString();
|
||||
params['@fromDate'] = fromDate;
|
||||
where.push('created_at >= @fromDate');
|
||||
|
||||
@@ -1403,12 +1405,15 @@ const gameLog = {
|
||||
);
|
||||
}
|
||||
if (toDays > 0) {
|
||||
const toDate = new Date(now.getTime() - toDays * 86400000).toISOString();
|
||||
const toDate = new Date(
|
||||
now.getTime() - toDays * 86400000
|
||||
).toISOString();
|
||||
params['@toDate'] = toDate;
|
||||
where.push('created_at < @toDate');
|
||||
}
|
||||
|
||||
const dateClause = where.length > 0 ? `WHERE ${where.join(' AND ')}` : '';
|
||||
const dateClause =
|
||||
where.length > 0 ? `WHERE ${where.join(' AND ')}` : '';
|
||||
await sqliteService.execute(
|
||||
(dbRow) => {
|
||||
data.push({ created_at: dbRow[0], time: dbRow[1] || 0 });
|
||||
@@ -1443,12 +1448,15 @@ const gameLog = {
|
||||
* 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.
|
||||
* @param {'time'|'count'} [sortBy='time'] - Sort by total time or visit count.
|
||||
* @returns {Promise<Array<{worldId: string, worldName: string, visitCount: number, totalTime: number}>>}
|
||||
*/
|
||||
async getMyTopWorlds(days = 0, limit = 5) {
|
||||
async getMyTopWorlds(days = 0, limit = 5, sortBy = 'time') {
|
||||
const results = [];
|
||||
const whereClause =
|
||||
days > 0 ? `AND created_at >= datetime('now', @daysOffset)` : '';
|
||||
const orderBy =
|
||||
sortBy === 'count' ? 'visit_count DESC' : 'total_time DESC';
|
||||
const params = { '@limit': limit };
|
||||
if (days > 0) {
|
||||
params['@daysOffset'] = `-${days} days`;
|
||||
@@ -1473,7 +1481,7 @@ const gameLog = {
|
||||
AND world_id LIKE 'wrld_%'
|
||||
${whereClause}
|
||||
GROUP BY world_id
|
||||
ORDER BY total_time DESC
|
||||
ORDER BY ${orderBy}
|
||||
LIMIT @limit`,
|
||||
params
|
||||
);
|
||||
|
||||
@@ -128,20 +128,6 @@ const database = {
|
||||
PRIMARY KEY (user_id, target_user_id, range_days, view_kind, exclude_key)
|
||||
)`
|
||||
);
|
||||
await sqliteService.executeNonQuery(
|
||||
`CREATE TABLE IF NOT EXISTS ${dbVars.userPrefix}_activity_top_worlds_cache_v2 (
|
||||
user_id TEXT NOT NULL,
|
||||
range_days INTEGER NOT NULL,
|
||||
rank_index INTEGER NOT NULL,
|
||||
world_id TEXT NOT NULL,
|
||||
world_name TEXT NOT NULL,
|
||||
visit_count INTEGER NOT NULL DEFAULT 0,
|
||||
total_time INTEGER NOT NULL DEFAULT 0,
|
||||
built_from_cursor TEXT NOT NULL DEFAULT '',
|
||||
built_at TEXT NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (user_id, range_days, rank_index)
|
||||
)`
|
||||
);
|
||||
await sqliteService.executeNonQuery(
|
||||
`CREATE TABLE IF NOT EXISTS ${dbVars.userPrefix}_friend_log_current (user_id TEXT PRIMARY KEY, display_name TEXT, trust_level TEXT, friend_number INTEGER)`
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user