package com.alttd.altitudeweb.mappers; import com.alttd.altitudeweb.database.luckperms.PlayerWithGroup; import com.alttd.altitudeweb.database.proxyplaytime.StaffPt; import com.alttd.altitudeweb.model.StaffPlaytimeDto; import org.springframework.stereotype.Service; import java.time.Instant; import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.util.*; import java.util.concurrent.TimeUnit; @Service public final class StaffPtToStaffPlaytimeMapper { private record PlaytimeInfo(long totalPlaytime, long lastPlayed) {} public List map(List sessions, List staffMembers, long from, long to, HashMap staffGroupsMap) { Map playtimeData = getUuidPlaytimeInfoMap(sessions, from, to); for (PlayerWithGroup staffMember : staffMembers) { if (!playtimeData.containsKey(staffMember.uuid())) { playtimeData.put(staffMember.uuid(), new PlaytimeInfo(0L, Long.MIN_VALUE)); } } List results = new ArrayList<>(playtimeData.size()); for (Map.Entry entry : playtimeData.entrySet()) { long lastPlayedMillis = entry.getValue().lastPlayed() == Long.MIN_VALUE ? 0L : entry.getValue().lastPlayed(); StaffPlaytimeDto dto = new StaffPlaytimeDto(); Optional first = staffMembers.stream() .filter(player -> player.uuid().equals(entry.getKey())).findFirst(); dto.setStaffMember(first.isPresent() ? first.get().username() : entry.getKey().toString()); dto.setStaffMember(staffMembers.stream() .filter(player -> player.uuid().equals(entry.getKey())) .map(PlayerWithGroup::username) .findFirst() .orElse(entry.getKey().toString()) ); dto.setLastPlayed(OffsetDateTime.ofInstant(Instant.ofEpochMilli(lastPlayedMillis), ZoneOffset.UTC)); dto.setPlaytime((int) TimeUnit.MILLISECONDS.toMinutes(entry.getValue().totalPlaytime())); if (first.isPresent()) { dto.setRole(staffGroupsMap.getOrDefault(first.get().group(), "Unknown")); } else { dto.setRole("Unknown"); } results.add(dto); } return results; } private Map getUuidPlaytimeInfoMap(List sessions, long from, long to) { Map playtimeData = new HashMap<>(); for (StaffPt session : sessions) { long overlapStart = Math.max(session.sessionStart(), from); long overlapEnd = Math.min(session.sessionEnd(), to); if (overlapEnd <= overlapStart) { continue; } PlaytimeInfo info = playtimeData.getOrDefault(session.uuid(), new PlaytimeInfo(0L, Long.MIN_VALUE)); long totalPlaytime = info.totalPlaytime() + (overlapEnd - overlapStart); long lastPlayed = Math.max(info.lastPlayed(), overlapEnd); playtimeData.put(session.uuid(), new PlaytimeInfo(totalPlaytime, lastPlayed)); } return playtimeData; } }