mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-28 20:17:42 +01:00
Added Session Calendar to Player page (#115 50%)
This commit is contained in:
parent
d19b929564
commit
e2d11e6dfe
@ -25,6 +25,7 @@ import com.djrapitops.plan.utilities.comparators.SessionStartComparator;
|
|||||||
import com.djrapitops.plan.utilities.file.FileUtil;
|
import com.djrapitops.plan.utilities.file.FileUtil;
|
||||||
import com.djrapitops.plan.utilities.html.HtmlStructure;
|
import com.djrapitops.plan.utilities.html.HtmlStructure;
|
||||||
import com.djrapitops.plan.utilities.html.HtmlUtils;
|
import com.djrapitops.plan.utilities.html.HtmlUtils;
|
||||||
|
import com.djrapitops.plan.utilities.html.graphs.PlayerCalendar;
|
||||||
import com.djrapitops.plan.utilities.html.graphs.PunchCardGraph;
|
import com.djrapitops.plan.utilities.html.graphs.PunchCardGraph;
|
||||||
import com.djrapitops.plan.utilities.html.graphs.pie.ServerPreferencePie;
|
import com.djrapitops.plan.utilities.html.graphs.pie.ServerPreferencePie;
|
||||||
import com.djrapitops.plan.utilities.html.graphs.pie.WorldPie;
|
import com.djrapitops.plan.utilities.html.graphs.pie.WorldPie;
|
||||||
@ -126,6 +127,11 @@ public class InspectPage extends Page {
|
|||||||
|
|
||||||
ServerAccordion serverAccordion = new ServerAccordion(profile, serverNames);
|
ServerAccordion serverAccordion = new ServerAccordion(profile, serverNames);
|
||||||
|
|
||||||
|
PlayerCalendar playerCalendar = new PlayerCalendar(allSessions, registered);
|
||||||
|
|
||||||
|
addValue("calendarSeries", playerCalendar.toCalendarSeries());
|
||||||
|
addValue("firstDay", 1);
|
||||||
|
|
||||||
addValue("accordionSessions", sessionsAccordion[0]);
|
addValue("accordionSessions", sessionsAccordion[0]);
|
||||||
addValue("accordionServers", serverAccordion.toHtml());
|
addValue("accordionServers", serverAccordion.toHtml());
|
||||||
addValue("sessionTabGraphViewFunctions", sessionsAccordion[1] + serverAccordion.toViewScript());
|
addValue("sessionTabGraphViewFunctions", sessionsAccordion[1] + serverAccordion.toViewScript());
|
||||||
|
@ -47,6 +47,12 @@ public class FormatUtils {
|
|||||||
return formatMilliseconds(Math.abs(after - before));
|
return formatMilliseconds(Math.abs(after - before));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String formatTimeStampISO8601NoClock(long epochMs) {
|
||||||
|
String format = "yyyy-MM-dd";
|
||||||
|
|
||||||
|
return format(epochMs, format);
|
||||||
|
}
|
||||||
|
|
||||||
public static String formatTimeStampDay(long epochMs) {
|
public static String formatTimeStampDay(long epochMs) {
|
||||||
String format = "MMMMM d";
|
String format = "MMMMM d";
|
||||||
|
|
||||||
|
@ -137,7 +137,8 @@ public class HtmlExport extends SpecificExport {
|
|||||||
"web/js/charts/punchCard.js",
|
"web/js/charts/punchCard.js",
|
||||||
"web/js/charts/serverPie.js",
|
"web/js/charts/serverPie.js",
|
||||||
"web/js/charts/worldPie.js",
|
"web/js/charts/worldPie.js",
|
||||||
"web/js/charts/healthGauge.js"
|
"web/js/charts/healthGauge.js",
|
||||||
|
"web/js/charts/sessionCalendar.js"
|
||||||
};
|
};
|
||||||
copyFromJar(resources);
|
copyFromJar(resources);
|
||||||
|
|
||||||
@ -164,7 +165,10 @@ public class HtmlExport extends SpecificExport {
|
|||||||
"web/plugins/jquery/jquery.min.js",
|
"web/plugins/jquery/jquery.min.js",
|
||||||
"web/plugins/bootstrap/js/bootstrap.js",
|
"web/plugins/bootstrap/js/bootstrap.js",
|
||||||
"web/plugins/jquery-datatable/skin/bootstrap/js/dataTables.bootstrap.js",
|
"web/plugins/jquery-datatable/skin/bootstrap/js/dataTables.bootstrap.js",
|
||||||
"web/plugins/jquery-datatable/jquery.dataTables.js"
|
"web/plugins/jquery-datatable/jquery.dataTables.js",
|
||||||
|
"web/plugins/fullcalendar/fullcalendar.min.js",
|
||||||
|
"web/plugins/fullcalendar/fullcalendar.min.css",
|
||||||
|
"web/plugins/momentjs/moment.js",
|
||||||
};
|
};
|
||||||
copyFromJar(resources);
|
copyFromJar(resources);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Licence is provided in the jar as license.yml also here:
|
||||||
|
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
|
||||||
|
*/
|
||||||
|
package com.djrapitops.plan.utilities.html.graphs;
|
||||||
|
|
||||||
|
import com.djrapitops.plan.data.container.PlayerKill;
|
||||||
|
import com.djrapitops.plan.data.container.Session;
|
||||||
|
import com.djrapitops.plan.utilities.FormatUtils;
|
||||||
|
import com.djrapitops.plugin.api.TimeAmount;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility for creating FullCalendar calendar event array on Player page.
|
||||||
|
*
|
||||||
|
* @author Rsl1122
|
||||||
|
*/
|
||||||
|
public class PlayerCalendar {
|
||||||
|
|
||||||
|
private final List<Session> allSessions;
|
||||||
|
private final long registered;
|
||||||
|
|
||||||
|
public PlayerCalendar(List<Session> allSessions, long registered) {
|
||||||
|
this.allSessions = allSessions;
|
||||||
|
this.registered = registered;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toCalendarSeries() {
|
||||||
|
StringBuilder series = new StringBuilder("[");
|
||||||
|
|
||||||
|
appendRegister(series);
|
||||||
|
appendDailyPlaytime(series);
|
||||||
|
appendSessionsAndKills(series);
|
||||||
|
|
||||||
|
return series.append("]").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendDailyPlaytime(StringBuilder series) {
|
||||||
|
Map<String, List<Session>> sessionsByDay = getSessionsByDay();
|
||||||
|
|
||||||
|
for (Map.Entry<String, List<Session>> entry : sessionsByDay.entrySet()) {
|
||||||
|
String day = entry.getKey();
|
||||||
|
|
||||||
|
List<Session> sessions = entry.getValue();
|
||||||
|
int sessionCount = sessions.size();
|
||||||
|
long playtime = sessions.stream().mapToLong(Session::getLength).sum();
|
||||||
|
|
||||||
|
series.append(",{title: 'Playtime: ").append(FormatUtils.formatTimeAmount(playtime))
|
||||||
|
.append("',start:'").append(day)
|
||||||
|
.append("',color: '#4CAF50'")
|
||||||
|
.append("}");
|
||||||
|
|
||||||
|
series.append(",{title: 'Sessions: ").append(sessionCount)
|
||||||
|
.append("',start:'").append(day)
|
||||||
|
.append("'}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, List<Session>> getSessionsByDay() {
|
||||||
|
Map<String, List<Session>> sessionsByDay = new HashMap<>();
|
||||||
|
for (Session session : allSessions) {
|
||||||
|
String day = FormatUtils.formatTimeStampISO8601NoClock(session.getSessionStart());
|
||||||
|
|
||||||
|
List<Session> sessionsOfDay = sessionsByDay.getOrDefault(day, new ArrayList<>());
|
||||||
|
sessionsOfDay.add(session);
|
||||||
|
sessionsByDay.put(day, sessionsOfDay);
|
||||||
|
}
|
||||||
|
return sessionsByDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendSessionsAndKills(StringBuilder series) {
|
||||||
|
long fiveMinutes = TimeAmount.MINUTE.ms() * 5L;
|
||||||
|
for (Session session : allSessions) {
|
||||||
|
String length = FormatUtils.formatTimeAmount(session.getLength());
|
||||||
|
|
||||||
|
series.append(",{title: 'Session: ").append(length)
|
||||||
|
.append("',start:").append(session.getSessionStart())
|
||||||
|
.append(",end:").append(session.getSessionEnd())
|
||||||
|
.append("}");
|
||||||
|
|
||||||
|
for (PlayerKill kill : session.getPlayerKills()) {
|
||||||
|
long time = kill.getTime();
|
||||||
|
|
||||||
|
series.append(",{title: 'Killed: ").append(kill.getVictim())
|
||||||
|
.append("',start:").append(time)
|
||||||
|
.append(",end:").append(time + fiveMinutes)
|
||||||
|
.append(",color: 'red'")
|
||||||
|
.append("}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendRegister(StringBuilder series) {
|
||||||
|
String registered = FormatUtils.formatTimeStampYear(this.registered);
|
||||||
|
|
||||||
|
series.append("{title: 'Registered: ").append(registered).append("'," +
|
||||||
|
"start: ").append(this.registered).append(",color: '#8BC34A'}");
|
||||||
|
}
|
||||||
|
}
|
30
Plan/src/main/resources/web/js/charts/sessionCalendar.js
Normal file
30
Plan/src/main/resources/web/js/charts/sessionCalendar.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
function sessionCalendar(id, events, firstDay) {
|
||||||
|
$(id).fullCalendar({
|
||||||
|
eventColor: '#009688',
|
||||||
|
eventLimit: true,
|
||||||
|
firstDay: firstDay,
|
||||||
|
|
||||||
|
eventRender: function (eventObj, $el) {
|
||||||
|
$el.popover({
|
||||||
|
content: eventObj.title,
|
||||||
|
trigger: 'hover',
|
||||||
|
placement: 'top',
|
||||||
|
container: 'body'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
events: events,
|
||||||
|
|
||||||
|
navLinks: true,
|
||||||
|
height: 'parent',
|
||||||
|
header: {
|
||||||
|
left: 'title',
|
||||||
|
center: '',
|
||||||
|
right: 'month agendaWeek agendaDay prev,next'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(function () {
|
||||||
|
$(id).fullCalendar('render')
|
||||||
|
}, 1000);
|
||||||
|
}
|
@ -450,6 +450,26 @@
|
|||||||
<div class="row clearfix">
|
<div class="row clearfix">
|
||||||
<!-- Sessions -->
|
<!-- Sessions -->
|
||||||
<div class="col-xs-12 col-sm-12 col-md-8 col-lg-8">
|
<div class="col-xs-12 col-sm-12 col-md-8 col-lg-8">
|
||||||
|
<div class="card">
|
||||||
|
<div class="header">
|
||||||
|
<div class="row clearfix">
|
||||||
|
<div class="col-xs-6 col-sm-6 col-lg-6">
|
||||||
|
<h2><i class="col-teal fa fa-calendar-o"></i> Session Calendar</h2>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-6 col-sm-6 col-lg-6">
|
||||||
|
<a href="javascript:void(0)" class="help material-icons pull-right"
|
||||||
|
data-trigger="focus" data-toggle="popover" data-placement="left"
|
||||||
|
data-container="body" data-html="true"
|
||||||
|
data-original-title="Session Calendar"
|
||||||
|
data-content="Calendar that contains information about sessions for each day.<br><br>Day numbers can be clicked to inspect a particular day in higher detail.<br><br>If a title is not visible you can hover over the box to see the title."
|
||||||
|
>help_outline</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="body">
|
||||||
|
<div id="sessionCalendar" style="height: 500px;" class="dashboard-flot-chart"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<div class="row clearfix">
|
<div class="row clearfix">
|
||||||
@ -646,6 +666,11 @@
|
|||||||
<script src="https://code.highcharts.com/modules/drilldown.js"></script>
|
<script src="https://code.highcharts.com/modules/drilldown.js"></script>
|
||||||
<script src="https://code.highcharts.com/modules/no-data-to-display.js"></script>
|
<script src="https://code.highcharts.com/modules/no-data-to-display.js"></script>
|
||||||
|
|
||||||
|
<!-- FullCalendar -->
|
||||||
|
<link rel='stylesheet' href='../plugins/fullcalendar/fullcalendar.min.css'/>
|
||||||
|
<script src='../plugins/momentjs/moment.js'></script>
|
||||||
|
<script src='../plugins/fullcalendar/fullcalendar.min.js'></script>
|
||||||
|
|
||||||
<!-- Font Awesome -->
|
<!-- Font Awesome -->
|
||||||
<script src="../plugins/font-awesome/fa-script.js"></script>
|
<script src="../plugins/font-awesome/fa-script.js"></script>
|
||||||
|
|
||||||
@ -656,13 +681,14 @@
|
|||||||
<script src="../js/charts/punchCard.js"></script>
|
<script src="../js/charts/punchCard.js"></script>
|
||||||
<script src="../js/charts/serverPie.js"></script>
|
<script src="../js/charts/serverPie.js"></script>
|
||||||
<script src="../js/charts/worldPie.js"></script>
|
<script src="../js/charts/worldPie.js"></script>
|
||||||
|
<script src="../js/charts/sessionCalendar.js"></script>
|
||||||
|
|
||||||
<!-- Chart Data -->
|
<!-- Chart Data -->
|
||||||
<script>
|
<script>
|
||||||
Highcharts.setOptions({
|
Highcharts.setOptions({
|
||||||
time: {
|
time: {
|
||||||
timezoneOffset: ${timeZone} * 60
|
timezoneOffset: ${timeZone} * 60
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
var serverSeries = {
|
var serverSeries = {
|
||||||
name: 'Server Playtime',
|
name: 'Server Playtime',
|
||||||
@ -682,12 +708,15 @@
|
|||||||
color: '#222',
|
color: '#222',
|
||||||
data: ${punchCardSeries}
|
data: ${punchCardSeries}
|
||||||
};
|
};
|
||||||
|
var calendarSeries =;
|
||||||
|
${calendarSeries}
|
||||||
|
var firstDay =
|
||||||
|
${firstDay}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Plan laod script -->
|
<!-- Plan laod script -->
|
||||||
<script>
|
<script>
|
||||||
$(function () {
|
$(function () {
|
||||||
|
|
||||||
$('.player-table').DataTable({
|
$('.player-table').DataTable({
|
||||||
responsive: true
|
responsive: true
|
||||||
});
|
});
|
||||||
@ -712,6 +741,7 @@
|
|||||||
worldPie('worldPie', worldSeries, gmSeries);
|
worldPie('worldPie', worldSeries, gmSeries);
|
||||||
serverPie('serverPie', serverSeries);
|
serverPie('serverPie', serverSeries);
|
||||||
punchCard('punchCard', punchcardSeries);
|
punchCard('punchCard', punchcardSeries);
|
||||||
|
sessionCalendar('#sessionCalendar', calendarSeries, firstDay);
|
||||||
${sessionTabGraphViewFunctions}
|
${sessionTabGraphViewFunctions}
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
Reference in New Issue
Block a user