1+ package dev.slne.surf.cloud.api.common.player.playtime
2+
3+ import dev.slne.surf.cloud.api.common.server.CloudServer
4+ import it.unimi.dsi.fastutil.objects.Object2ObjectMap
5+ import it.unimi.dsi.fastutil.objects.ObjectList
6+ import it.unimi.dsi.fastutil.objects.ObjectSet
7+ import java.time.ZonedDateTime
8+ import kotlin.time.Duration
9+
10+ /* *
11+ * Provides a comprehensive analytical view of playtime data, allowing various queries and analyses
12+ * based on servers, categories, and timeframes.
13+ *
14+ * This interface is immutable and provides methods to perform detailed aggregations and analytics
15+ * without altering the underlying data.
16+ */
17+ interface Playtime {
18+
19+ /* *
20+ * Returns the total playtime across all servers and categories.
21+ *
22+ * @param since Optional start time. If provided, only playtime after this timestamp is considered.
23+ * @return The summed total playtime as a [Duration].
24+ */
25+ fun sumPlaytimes (since : ZonedDateTime ? = null): Duration
26+
27+ /* *
28+ * Returns the total playtime for a specific category.
29+ *
30+ * @param category The category to filter by.
31+ * @param since Optional start time to filter playtime.
32+ * @return The summed total playtime for the category as a [Duration].
33+ */
34+ fun sumByCategory (category : String , since : ZonedDateTime ? = null): Duration
35+
36+ /* *
37+ * Returns the total playtime on a specific server identified by its name.
38+ *
39+ * @param server The server name to filter by.
40+ * @param since Optional start time to filter playtime.
41+ * @return The summed total playtime for the specified server as a [Duration].
42+ */
43+ fun sumByServer (server : String , since : ZonedDateTime ? = null): Duration
44+
45+ /* *
46+ * Returns the total playtime on a specific [CloudServer].
47+ *
48+ * @param server The [CloudServer] to filter by.
49+ * @param since Optional start time to filter playtime.
50+ * @return The summed total playtime for the specified server as a [Duration].
51+ */
52+ fun sumByServer (server : CloudServer , since : ZonedDateTime ? = null): Duration {
53+ return sumByServer(server.name, since)
54+ }
55+
56+ /* *
57+ * Returns a set of all distinct categories present in the playtime data.
58+ *
59+ * @return An [ObjectSet] of unique category names.
60+ */
61+ fun getCategories (): ObjectSet <String >
62+
63+ /* *
64+ * Returns a set of all distinct server names present in the playtime data.
65+ *
66+ * @return An [ObjectSet] of unique server names.
67+ */
68+ fun getServers (): ObjectSet <String >
69+
70+ /* *
71+ * Returns the total playtime for a specific server and optionally a specific category.
72+ *
73+ * @param server The server name.
74+ * @param category Optional category to further filter results.
75+ * @param since Optional start time to filter playtime.
76+ * @return The summed total playtime matching the specified filters as a [Duration].
77+ */
78+ fun playtimeFor (
79+ server : String ,
80+ category : String? = null,
81+ since : ZonedDateTime ? = null
82+ ): Duration
83+
84+ /* *
85+ * Returns a mapping of servers to their respective total playtime durations.
86+ *
87+ * @param since Optional start time to filter playtime.
88+ * @return An [Object2ObjectMap] where keys are server names and values are durations.
89+ */
90+ fun playtimesPerServer (since : ZonedDateTime ? = null): Object2ObjectMap <String , Duration >
91+
92+ /* *
93+ * Returns a mapping of categories to their respective total playtime durations.
94+ *
95+ * @param since Optional start time to filter playtime.
96+ * @return An [Object2ObjectMap] where keys are category names and values are durations.
97+ */
98+ fun playtimesPerCategory (since : ZonedDateTime ? = null): Object2ObjectMap <String , Duration >
99+
100+ /* *
101+ * Returns the average playtime per server, optionally filtered by category and start time.
102+ *
103+ * @param category Optional category to filter by.
104+ * @param since Optional start time to filter playtime.
105+ * @return The average playtime across servers as a [Duration].
106+ */
107+ fun averagePlaytimePerServer (category : String? = null, since : ZonedDateTime ? = null): Duration
108+
109+ /* *
110+ * Generates a timeline mapping timestamps to accumulated playtime durations, grouped by specified intervals.
111+ * Each interval represents a bucket of time starting at the beginning of the interval and includes the total
112+ * playtime that occurred within that interval. This is particularly useful for analyzing player activity trends,
113+ * identifying peak playing times, or generating visualizations such as heatmaps and activity charts.
114+ *
115+ * For example, if you choose an hourly interval, each timestamp in the resulting map will correspond
116+ * precisely to the start of that hour, with its associated duration representing the sum of all playtime
117+ * recorded between that hour and the start of the next hour.
118+ *
119+ * ### Example use case:
120+ *
121+ * Suppose you want to analyze player activity throughout the last day to determine peak gaming hours on
122+ * the server named "PvP-Arena" within the "competitive" category. You could use:
123+ *
124+ * ```kotlin
125+ * val hourlyTimeline = playtime.timeline(
126+ * interval = 1.hours,
127+ * category = "competitive",
128+ * server = "PvP-Arena"
129+ * )
130+ *
131+ * hourlyTimeline.forEach { (hour, duration) ->
132+ * println("Playtime from $hour to ${hour.plusHours(1)}: $duration")
133+ * }
134+ * ```
135+ *
136+ * The resulting output might look like:
137+ *
138+ * ```
139+ * Playtime from 2025-04-08T14:00Z to 2025-04-08T15:00Z: 30m
140+ * Playtime from 2025-04-08T15:00Z to 2025-04-08T16:00Z: 45m
141+ * Playtime from 2025-04-08T16:00Z to 2025-04-08T17:00Z: 1h
142+ * ...
143+ * ```
144+ *
145+ * This clearly illustrates player activity peaks, enabling targeted actions such as scheduling server events,
146+ * balancing loads, or informing community engagement strategies.
147+ *
148+ * @param interval The duration of each interval (e.g., hourly, daily, weekly).
149+ * @param category Optional category filter. If specified, only playtime matching this category is considered.
150+ * @param server Optional server filter. If specified, only playtime on this particular server is included.
151+ * @return An [Object2ObjectMap] mapping interval-start timestamps to the total accumulated playtime durations
152+ * within each interval.
153+ */
154+ fun timeline (
155+ interval : Duration ,
156+ category : String? = null,
157+ server : String? = null
158+ ): Object2ObjectMap <ZonedDateTime , Duration >
159+
160+ /* *
161+ * Retrieves a ranked list of servers sorted by total playtime in descending order.
162+ *
163+ * @param limit Maximum number of results to return.
164+ * @param since Optional start time to filter playtime.
165+ * @return An [ObjectList] of pairs, each containing a server name and its corresponding playtime duration.
166+ */
167+ fun topServers (limit : Int = 5, since : ZonedDateTime ? = null): ObjectList <Pair <String , Duration >>
168+
169+ /* *
170+ * Retrieves a ranked list of categories sorted by total playtime in descending order.
171+ *
172+ * @param limit Maximum number of results to return.
173+ * @param since Optional start time to filter playtime.
174+ * @return An [ObjectList] of pairs, each containing a category name and its corresponding playtime duration.
175+ */
176+ fun topCategories (limit : Int = 5, since : ZonedDateTime ? = null): ObjectList <Pair <String , Duration >>
177+ }
0 commit comments