AnalyticsTimeline.java
package org.darkroomlibrary.utils;
import org.darkroomlibrary.web.dto.query.PageQuery;
import org.darkroomlibrary.web.view.DailyCount;
import org.darkroomlibrary.web.view.MetricPoint;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Builds date windows and chart-ready daily counts for reporting endpoints.
*/
public final class AnalyticsTimeline {
private static final int MAX_LOOKBACK_DAYS = 3_650;
private AnalyticsTimeline() {
}
public static PageQuery queryWindow(Integer lookbackDays) {
int days = normalizeDays(lookbackDays);
LocalDateTime now = LocalDateTime.now();
LocalDateTime start = now.toLocalDate().minusDays(days).atStartOfDay();
return PageQuery.builder()
.startTime(start)
.endTime(now)
.build();
}
public static List<MetricPoint> toDailyMetrics(Integer lookbackDays, List<DailyCount> dailyCounts) {
int days = normalizeDays(lookbackDays);
LocalDate firstDay = LocalDate.now().minusDays(days);
LocalDate lastDay = LocalDate.now();
Map<LocalDate, Integer> counts = new LinkedHashMap<>();
for (LocalDate day = firstDay; !day.isAfter(lastDay); day = day.plusDays(1)) {
counts.put(day, 0);
}
List<DailyCount> safeCounts = dailyCounts == null ? List.of() : dailyCounts;
for (DailyCount dailyCount : safeCounts) {
if (dailyCount == null || dailyCount.getDay() == null) {
continue;
}
counts.computeIfPresent(
dailyCount.getDay(),
(ignored, count) -> count + Math.max(0, dailyCount.getCount() == null ? 0 : dailyCount.getCount())
);
}
return counts.entrySet().stream()
.filter(entry -> entry.getValue() > 0)
.map(entry -> new MetricPoint(formatDay(entry.getKey()), entry.getValue()))
.collect(Collectors.toList());
}
private static int normalizeDays(Integer lookbackDays) {
if (lookbackDays == null || lookbackDays < 0) {
return 0;
}
return Math.min(lookbackDays, MAX_LOOKBACK_DAYS);
}
private static String formatDay(LocalDate day) {
return String.format("%02d-%02d", day.getMonthValue(), day.getDayOfMonth());
}
}