Improve 'Previous Instances' grouping behavior (#1305)

* Group user's previous instances by location AND calendar dates for better clarity

* date grouping in local timezone instead of UTC

* prevent zero-time records due to OnPlayerJoined and OnPlayerLeft happening on different calendar days

* fix deleteGameLogUserInstance behavior to be consistent with new history grouping

* change 'previous instances' algorithm

group multiple events together into single session record, even if rejoins occur within 1 hour on the same instance
delete button also deletes all related gamelog_join_leave events correctly by their id

* replace questionable condition with proper one
This commit is contained in:
osiris-plus
2025-07-24 12:37:41 +03:00
committed by GitHub
parent c4533fd9d0
commit 260854d538
2 changed files with 44 additions and 21 deletions

View File

@@ -165,7 +165,8 @@
database.deleteGameLogInstance({
id: props.previousInstancesUserDialog.userRef.id,
displayName: props.previousInstancesUserDialog.userRef.displayName,
location: row.location
location: row.location,
events: row.events
});
removeFromArray(previousInstancesUserDialogTable.data, row);
}

View File

@@ -867,36 +867,58 @@ const gameLog = {
},
async getPreviousInstancesByUserId(input) {
var data = new Map();
var groupingTimeTolerance = 1 * 60 * 60 * 1000; // 1 hour
var data = new Set();
var currentGroup;
var prevEvent;
await sqliteService.execute(
(dbRow) => {
var time = 0;
if (dbRow[2]) {
time = dbRow[2];
var [created_at_iso, created_at_ts, location, time, worldName, groupName, eventId, eventType] = dbRow;
if (
!currentGroup
|| currentGroup.location !== location
|| (
(created_at_ts - currentGroup.last_ts) > groupingTimeTolerance // groups multiple OnPlayerJoined and OnPlayerLeft together if they are within time tolerance limit
&& !(prevEvent === "OnPlayerJoined" && eventType === "OnPlayerLeft") // allows OnPlayerLeft to connect with nearby OnPlayerJoined
)
) {
currentGroup = {
created_at: created_at_iso,
location,
time,
worldName,
groupName,
events: [eventId],
last_ts: created_at_ts,
};
data.add(currentGroup);
} else {
currentGroup.time += time;
currentGroup.last_ts = created_at_ts;
currentGroup.events.push(eventId);
}
var ref = data.get(dbRow[1]);
if (typeof ref !== 'undefined') {
time += ref.time;
}
var row = {
created_at: dbRow[0],
location: dbRow[1],
time,
worldName: dbRow[3],
groupName: dbRow[4]
};
data.set(row.location, row);
prevEvent = eventType;
},
`SELECT DISTINCT gamelog_join_leave.created_at, gamelog_join_leave.location, gamelog_join_leave.time, gamelog_location.world_name, gamelog_location.group_name
`
WITH grouped_locations AS (
SELECT DISTINCT location, world_name, group_name
FROM gamelog_location
)
SELECT gamelog_join_leave.created_at, strftime("%s", gamelog_join_leave.created_at) * 1000 created_at_ts, gamelog_join_leave.location, gamelog_join_leave.time, grouped_locations.world_name, grouped_locations.group_name, gamelog_join_leave.id, gamelog_join_leave.type
FROM gamelog_join_leave
INNER JOIN gamelog_location ON gamelog_join_leave.location = gamelog_location.location
INNER JOIN grouped_locations ON gamelog_join_leave.location = grouped_locations.location
WHERE user_id = @userId OR display_name = @displayName
ORDER BY gamelog_join_leave.id DESC`,
ORDER BY gamelog_join_leave.id ASC`,
{
'@userId': input.id,
'@displayName': input.displayName
}
);
return data;
},
@@ -1126,7 +1148,7 @@ const gameLog = {
deleteGameLogInstance(input) {
sqliteService.executeNonQuery(
`DELETE FROM gamelog_join_leave WHERE (user_id = @user_id OR display_name = @displayName) AND (location = @location)`,
`DELETE FROM gamelog_join_leave WHERE (user_id = @user_id OR display_name = @displayName) AND (location = @location) AND (id in (${input.events.join(',')}))`,
{
'@user_id': input.id,
'@displayName': input.displayName,