mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-01-02 22:47:37 +01:00
parent
757bd550be
commit
33b0c1e7ce
@ -282,7 +282,7 @@ public class GraphJSONCreator {
|
||||
return createUniqueAndNewJSON(lineGraphs, uniquePerDay, newPerDay, TimeUnit.HOURS.toMillis(1L));
|
||||
}
|
||||
|
||||
public String serverCalendarJSON(ServerUUID serverUUID) {
|
||||
public Map<String, Object> serverCalendarJSON(ServerUUID serverUUID) {
|
||||
Database db = dbSystem.getDatabase();
|
||||
long now = System.currentTimeMillis();
|
||||
long twoYearsAgo = now - TimeUnit.DAYS.toMillis(730L);
|
||||
@ -299,17 +299,17 @@ public class GraphJSONCreator {
|
||||
NavigableMap<Long, Integer> sessionsPerDay = db.query(
|
||||
SessionQueries.sessionCountPerDay(twoYearsAgo, now, timeZoneOffset, serverUUID)
|
||||
);
|
||||
return "{\"data\":" +
|
||||
return Map.of("data",
|
||||
graphs.calendar().serverCalendar(
|
||||
uniquePerDay,
|
||||
newPerDay,
|
||||
playtimePerDay,
|
||||
sessionsPerDay
|
||||
).toCalendarSeries() +
|
||||
",\"firstDay\":" + 1 + '}';
|
||||
).getEntries(),
|
||||
"firstDay", 1);
|
||||
}
|
||||
|
||||
public String networkCalendarJSON() {
|
||||
public Map<String, Object> networkCalendarJSON() {
|
||||
Database db = dbSystem.getDatabase();
|
||||
long now = System.currentTimeMillis();
|
||||
long twoYearsAgo = now - TimeUnit.DAYS.toMillis(730L);
|
||||
@ -326,14 +326,14 @@ public class GraphJSONCreator {
|
||||
NavigableMap<Long, Integer> sessionsPerDay = db.query(
|
||||
SessionQueries.sessionCountPerDay(twoYearsAgo, now, timeZoneOffset)
|
||||
);
|
||||
return "{\"data\":" +
|
||||
return Map.of("data",
|
||||
graphs.calendar().serverCalendar(
|
||||
uniquePerDay,
|
||||
newPerDay,
|
||||
playtimePerDay,
|
||||
sessionsPerDay
|
||||
).toCalendarSeries() +
|
||||
",\"firstDay\":" + 1 + '}';
|
||||
).getEntries(),
|
||||
"firstDay", 1);
|
||||
}
|
||||
|
||||
public Map<String, Object> serverWorldPieJSONAsMap(ServerUUID serverUUID) {
|
||||
|
@ -27,17 +27,19 @@ import java.util.Optional;
|
||||
public class CalendarEntry {
|
||||
|
||||
private final String title;
|
||||
private final Serializable value;
|
||||
private final Serializable start;
|
||||
private Serializable end;
|
||||
private String color;
|
||||
|
||||
private CalendarEntry(String title, Serializable start) {
|
||||
private CalendarEntry(String title, Serializable value, Serializable start) {
|
||||
this.title = title;
|
||||
this.value = value;
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public static CalendarEntry of(String title, Serializable start) {
|
||||
return new CalendarEntry(title, start);
|
||||
public static CalendarEntry of(String title, Serializable value, Serializable start) {
|
||||
return new CalendarEntry(title, value, start);
|
||||
}
|
||||
|
||||
public CalendarEntry withEnd(Serializable end) {
|
||||
@ -50,10 +52,14 @@ public class CalendarEntry {
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
public Serializable getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public Serializable getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Serializable getStart() {
|
||||
return start;
|
||||
}
|
||||
@ -70,6 +76,7 @@ public class CalendarEntry {
|
||||
public String toString() {
|
||||
return "{" +
|
||||
"title:'" + title + '\'' +
|
||||
", value:" + value +
|
||||
", start:'" + start + '\'' +
|
||||
(end != null ? ", end='" + end + '\'' : "") +
|
||||
(color != null ? ", color='" + color + '\'' : "") +
|
||||
|
@ -68,7 +68,7 @@ public class CalendarFactory {
|
||||
) {
|
||||
return new ServerCalendar(
|
||||
uniquePerDay, newPerDay, playtimePerDay, sessionsPerDay,
|
||||
formatters.iso8601NoClockTZIndependentLong(), formatters.timeAmount(), theme, locale
|
||||
formatters.iso8601NoClockTZIndependentLong(), theme
|
||||
);
|
||||
}
|
||||
}
|
@ -72,9 +72,8 @@ public class PlayerCalendar {
|
||||
List<CalendarEntry> entries = new ArrayList<>();
|
||||
|
||||
entries.add(CalendarEntry
|
||||
.of(locale.getString(HtmlLang.LABEL_REGISTERED) + ": " + year.apply(registered),
|
||||
registered
|
||||
).withColor(theme.getValue(ThemeVal.LIGHT_GREEN))
|
||||
.of(HtmlLang.LABEL_REGISTERED.getKey(), registered, registered + timeZone.getOffset(registered))
|
||||
.withColor(theme.getValue(ThemeVal.LIGHT_GREEN))
|
||||
);
|
||||
|
||||
Map<String, List<FinishedSession>> sessionsByDay = getSessionsByDay();
|
||||
@ -87,30 +86,30 @@ public class PlayerCalendar {
|
||||
long playtime = sessions.stream().mapToLong(FinishedSession::getLength).sum();
|
||||
|
||||
entries.add(CalendarEntry
|
||||
.of(locale.getString(HtmlLang.LABEL_PLAYTIME) + ": " + timeAmount.apply(playtime), day)
|
||||
.of(HtmlLang.LABEL_PLAYTIME.getKey(), playtime, day)
|
||||
.withColor(theme.getValue(ThemeVal.GREEN))
|
||||
);
|
||||
entries.add(CalendarEntry.of(locale.getString(HtmlLang.SIDE_SESSIONS) + ": " + sessionCount, day));
|
||||
entries.add(CalendarEntry.of(HtmlLang.SIDE_SESSIONS.getKey(), sessionCount, day)
|
||||
.withColor(theme.getValue(ThemeVal.TEAL)));
|
||||
}
|
||||
|
||||
long fiveMinutes = TimeUnit.MINUTES.toMillis(5L);
|
||||
|
||||
for (FinishedSession session : allSessions) {
|
||||
String length = timeAmount.apply(session.getLength());
|
||||
long start = session.getStart();
|
||||
long end = session.getEnd();
|
||||
|
||||
entries.add(CalendarEntry
|
||||
.of(length + " " + locale.getString(HtmlLang.SESSION),
|
||||
start + timeZone.getOffset(start))
|
||||
.of(HtmlLang.SESSION.getKey(), session.getLength(), start + timeZone.getOffset(start))
|
||||
.withEnd(end + timeZone.getOffset(end))
|
||||
.withColor(theme.getValue(ThemeVal.TEAL))
|
||||
);
|
||||
|
||||
for (PlayerKill kill : session.getExtraData(PlayerKills.class).map(PlayerKills::asList).orElseGet(ArrayList::new)) {
|
||||
long time = kill.getDate();
|
||||
String victim = kill.getVictim().getName();
|
||||
entries.add(CalendarEntry
|
||||
.of(locale.getString(HtmlLang.KILLED) + ": " + victim, time)
|
||||
.of(HtmlLang.KILLED.getKey(), victim, time)
|
||||
.withEnd(time + fiveMinutes)
|
||||
.withColor(theme.getValue(ThemeVal.RED))
|
||||
);
|
||||
|
@ -17,14 +17,11 @@
|
||||
package com.djrapitops.plan.delivery.rendering.json.graphs.calendar;
|
||||
|
||||
import com.djrapitops.plan.delivery.formatting.Formatter;
|
||||
import com.djrapitops.plan.settings.locale.Locale;
|
||||
import com.djrapitops.plan.settings.locale.lang.HtmlLang;
|
||||
import com.djrapitops.plan.settings.theme.Theme;
|
||||
import com.djrapitops.plan.settings.theme.ThemeVal;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.SortedMap;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Utility for creating FullCalendar calendar event array on Player page.
|
||||
@ -39,9 +36,7 @@ public class ServerCalendar {
|
||||
private final SortedMap<Long, Long> playtimePerDay;
|
||||
|
||||
private final Formatter<Long> iso8601TZIndependent;
|
||||
private final Formatter<Long> timeAmount;
|
||||
private final Theme theme;
|
||||
private final Locale locale;
|
||||
|
||||
ServerCalendar(
|
||||
SortedMap<Long, Integer> uniquePerDay,
|
||||
@ -49,37 +44,26 @@ public class ServerCalendar {
|
||||
SortedMap<Long, Long> playtimePerDay,
|
||||
NavigableMap<Long, Integer> sessionsPerDay,
|
||||
Formatter<Long> iso8601TZIndependent,
|
||||
Formatter<Long> timeAmount,
|
||||
Theme theme,
|
||||
Locale locale
|
||||
Theme theme
|
||||
) {
|
||||
this.uniquePerDay = uniquePerDay;
|
||||
this.newPerDay = newPerDay;
|
||||
this.iso8601TZIndependent = iso8601TZIndependent;
|
||||
this.timeAmount = timeAmount;
|
||||
this.sessionsPerDay = sessionsPerDay;
|
||||
this.playtimePerDay = playtimePerDay;
|
||||
this.theme = theme;
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
public String toCalendarSeries() {
|
||||
StringBuilder series = new StringBuilder("[");
|
||||
|
||||
series.append("{\"title\": \"badcode\",\"start\":0}");
|
||||
appendTimeZoneOffsetData(series);
|
||||
|
||||
return series.append("]").toString();
|
||||
public List<CalendarEntry> getEntries() {
|
||||
List<CalendarEntry> entries = new ArrayList<>();
|
||||
appendUniquePlayers(entries);
|
||||
appendNewPlayers(entries);
|
||||
appendSessionCounts(entries);
|
||||
appendPlaytime(entries);
|
||||
return entries;
|
||||
}
|
||||
|
||||
private void appendTimeZoneOffsetData(StringBuilder series) {
|
||||
appendUniquePlayers(series);
|
||||
appendNewPlayers(series);
|
||||
appendSessionCounts(series);
|
||||
appendPlaytime(series);
|
||||
}
|
||||
|
||||
private void appendNewPlayers(StringBuilder series) {
|
||||
private void appendNewPlayers(List<CalendarEntry> entries) {
|
||||
for (Map.Entry<Long, Integer> entry : newPerDay.entrySet()) {
|
||||
int newPlayers = entry.getValue();
|
||||
if (newPlayers <= 0) {
|
||||
@ -89,14 +73,12 @@ public class ServerCalendar {
|
||||
Long key = entry.getKey();
|
||||
String day = iso8601TZIndependent.apply(key);
|
||||
|
||||
series.append(",{\"title\": \"").append(locale.get(HtmlLang.NEW_CALENDAR)).append(" ").append(newPlayers)
|
||||
.append("\",\"start\":\"").append(day)
|
||||
.append("\",\"color\": \"").append(theme.getValue(ThemeVal.LIGHT_GREEN)).append('"')
|
||||
.append("}");
|
||||
entries.add(CalendarEntry.of(HtmlLang.NEW_CALENDAR.getKey(), newPlayers, day)
|
||||
.withColor(theme.getValue(ThemeVal.LIGHT_GREEN)));
|
||||
}
|
||||
}
|
||||
|
||||
private void appendUniquePlayers(StringBuilder series) {
|
||||
private void appendUniquePlayers(List<CalendarEntry> entries) {
|
||||
for (Map.Entry<Long, Integer> entry : uniquePerDay.entrySet()) {
|
||||
long uniquePlayers = entry.getValue();
|
||||
if (uniquePlayers <= 0) {
|
||||
@ -106,14 +88,11 @@ public class ServerCalendar {
|
||||
Long key = entry.getKey();
|
||||
String day = iso8601TZIndependent.apply(key);
|
||||
|
||||
series.append(",{\"title\": \"").append(locale.get(HtmlLang.UNIQUE_CALENDAR)).append(" ").append(uniquePlayers)
|
||||
.append("\",\"start\":\"").append(day)
|
||||
.append("\"}");
|
||||
|
||||
entries.add(CalendarEntry.of(HtmlLang.UNIQUE_CALENDAR.getKey(), uniquePlayers, day));
|
||||
}
|
||||
}
|
||||
|
||||
private void appendPlaytime(StringBuilder series) {
|
||||
private void appendPlaytime(List<CalendarEntry> entries) {
|
||||
for (Map.Entry<Long, Long> entry : playtimePerDay.entrySet()) {
|
||||
long playtime = entry.getValue();
|
||||
if (playtime <= 0) {
|
||||
@ -122,14 +101,12 @@ public class ServerCalendar {
|
||||
Long key = entry.getKey();
|
||||
String day = iso8601TZIndependent.apply(key);
|
||||
|
||||
series.append(",{\"title\": \"").append(locale.get(HtmlLang.LABEL_PLAYTIME)).append(": ").append(timeAmount.apply(playtime))
|
||||
.append("\",\"start\":\"").append(day)
|
||||
.append("\",\"color\": \"").append(theme.getValue(ThemeVal.GREEN)).append('"')
|
||||
.append("}");
|
||||
entries.add(CalendarEntry.of(HtmlLang.LABEL_PLAYTIME.getKey(), playtime, day)
|
||||
.withColor(theme.getValue(ThemeVal.GREEN)));
|
||||
}
|
||||
}
|
||||
|
||||
private void appendSessionCounts(StringBuilder series) {
|
||||
private void appendSessionCounts(List<CalendarEntry> entries) {
|
||||
for (Map.Entry<Long, Integer> entry : sessionsPerDay.entrySet()) {
|
||||
int sessionCount = entry.getValue();
|
||||
if (sessionCount <= 0) {
|
||||
@ -138,10 +115,8 @@ public class ServerCalendar {
|
||||
Long key = entry.getKey();
|
||||
String day = iso8601TZIndependent.apply(key);
|
||||
|
||||
series.append(",{\"title\": \"").append(locale.get(HtmlLang.SIDE_SESSIONS)).append(": ").append(sessionCount)
|
||||
.append("\",\"start\":\"").append(day)
|
||||
.append("\",\"color\": \"").append(theme.getValue(ThemeVal.TEAL)).append('"')
|
||||
.append("}");
|
||||
entries.add(CalendarEntry.of(HtmlLang.SIDE_SESSIONS.getKey(), sessionCount, day)
|
||||
.withColor(theme.getValue(ThemeVal.TEAL)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,43 @@
|
||||
import React from "react";
|
||||
import FullCalendar from '@fullcalendar/react'
|
||||
import dayGridPlugin from '@fullcalendar/daygrid'
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {formatTimeAmount} from "../../util/format/TimeAmountFormat.js";
|
||||
import {formatDate, useDatePreferences} from "../text/FormattedDate.jsx";
|
||||
import {useTimePreferences} from "../text/FormattedTime.jsx";
|
||||
|
||||
const PlayerSessionCalendar = ({series, firstDay}) => {
|
||||
const {t} = useTranslation();
|
||||
|
||||
const timePreferences = useTimePreferences();
|
||||
const datePreferences = useDatePreferences();
|
||||
|
||||
const formatDateEasy = date => {
|
||||
return formatDate(date, datePreferences.offset, datePreferences.pattern, false, datePreferences.recentDaysPattern, t);
|
||||
}
|
||||
|
||||
const formatTitle = entry => {
|
||||
switch (entry.title) {
|
||||
case 'html.label.session':
|
||||
return formatTimeAmount(timePreferences, entry.value) + ' ' + t(entry.title);
|
||||
case 'html.label.playtime':
|
||||
return t(entry.title) + ": " + formatTimeAmount(timePreferences, entry.value)
|
||||
case 'html.label.registered':
|
||||
return t(entry.title) + ": " + formatDateEasy(entry.value)
|
||||
default:
|
||||
return t(entry.title) + ": " + entry.value;
|
||||
}
|
||||
}
|
||||
|
||||
const actualSeries = series.map(entry => {
|
||||
return {
|
||||
title: formatTitle(entry),
|
||||
start: entry.start,
|
||||
end: entry.end,
|
||||
color: entry.color
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<FullCalendar
|
||||
plugins={[dayGridPlugin]}
|
||||
@ -20,7 +55,7 @@ const PlayerSessionCalendar = ({series, firstDay}) => {
|
||||
center: '',
|
||||
right: 'dayGridMonth dayGridWeek dayGridDay today prev next'
|
||||
}}
|
||||
events={(_fetchInfo, successCallback) => successCallback(series)}
|
||||
events={(_fetchInfo, successCallback) => successCallback(actualSeries)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import interactionPlugin from '@fullcalendar/interaction'
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||
import {faHandPointer} from "@fortawesome/free-regular-svg-icons";
|
||||
import {useTimePreferences} from "../text/FormattedTime.jsx";
|
||||
import {formatTimeAmount} from "../../util/format/TimeAmountFormat.js";
|
||||
|
||||
const ServerCalendar = ({series, firstDay, onSelect}) => {
|
||||
const {t} = useTranslation();
|
||||
@ -14,6 +16,28 @@ const ServerCalendar = ({series, firstDay, onSelect}) => {
|
||||
top: "0.5rem",
|
||||
right: "1rem"
|
||||
};
|
||||
const timePreferences = useTimePreferences();
|
||||
|
||||
const formatTitle = entry => {
|
||||
switch (entry.title) {
|
||||
case 'html.label.playtime':
|
||||
return t(entry.title) + ": " + formatTimeAmount(timePreferences, entry.value)
|
||||
case 'html.calendar.unique':
|
||||
case 'html.calendar.new':
|
||||
return t(entry.title) + " " + entry.value
|
||||
default:
|
||||
return t(entry.title) + ": " + entry.value;
|
||||
}
|
||||
}
|
||||
|
||||
const actualSeries = series.map(entry => {
|
||||
return {
|
||||
title: formatTitle(entry),
|
||||
start: entry.start,
|
||||
end: entry.end,
|
||||
color: entry.color
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<div id={'server-calendar'}>
|
||||
@ -38,7 +62,7 @@ const ServerCalendar = ({series, firstDay, onSelect}) => {
|
||||
selectable={Boolean(onSelect)}
|
||||
select={onSelect}
|
||||
unselectAuto={true}
|
||||
events={(_fetchInfo, successCallback) => successCallback(series)}
|
||||
events={(_fetchInfo, successCallback) => successCallback(actualSeries)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user