mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-27 03:27:37 +01:00
Added activity graphs to query results
This commit is contained in:
parent
c1d53c27d3
commit
a3c16b4b21
@ -16,8 +16,10 @@
|
||||
*/
|
||||
package com.djrapitops.plan.delivery.webserver.resolver.json;
|
||||
|
||||
import com.djrapitops.plan.delivery.domain.DateMap;
|
||||
import com.djrapitops.plan.delivery.formatting.Formatters;
|
||||
import com.djrapitops.plan.delivery.rendering.json.PlayersTableJSONCreator;
|
||||
import com.djrapitops.plan.delivery.rendering.json.graphs.GraphJSONCreator;
|
||||
import com.djrapitops.plan.delivery.web.resolver.MimeType;
|
||||
import com.djrapitops.plan.delivery.web.resolver.Resolver;
|
||||
import com.djrapitops.plan.delivery.web.resolver.Response;
|
||||
@ -30,12 +32,14 @@ import com.djrapitops.plan.settings.config.paths.TimeSettings;
|
||||
import com.djrapitops.plan.settings.locale.Locale;
|
||||
import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plan.storage.database.Database;
|
||||
import com.djrapitops.plan.storage.database.queries.analysis.NetworkActivityIndexQueries;
|
||||
import com.djrapitops.plan.storage.database.queries.filter.Filter;
|
||||
import com.djrapitops.plan.storage.database.queries.filter.FilterQuery;
|
||||
import com.djrapitops.plan.storage.database.queries.filter.QueryFilters;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.playertable.QueryTablePlayersQuery;
|
||||
import com.djrapitops.plan.storage.json.JSONStorage;
|
||||
import com.djrapitops.plan.utilities.java.Maps;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@ -54,6 +58,7 @@ public class QueryJSONResolver implements Resolver {
|
||||
private final PlanConfig config;
|
||||
private final DBSystem dbSystem;
|
||||
private final JSONStorage jsonStorage;
|
||||
private final GraphJSONCreator graphJSONCreator;
|
||||
private final Locale locale;
|
||||
private final Formatters formatters;
|
||||
|
||||
@ -63,6 +68,7 @@ public class QueryJSONResolver implements Resolver {
|
||||
PlanConfig config,
|
||||
DBSystem dbSystem,
|
||||
JSONStorage jsonStorage,
|
||||
GraphJSONCreator graphJSONCreator,
|
||||
Locale locale,
|
||||
Formatters formatters
|
||||
) {
|
||||
@ -70,6 +76,7 @@ public class QueryJSONResolver implements Resolver {
|
||||
this.config = config;
|
||||
this.dbSystem = dbSystem;
|
||||
this.jsonStorage = jsonStorage;
|
||||
this.graphJSONCreator = graphJSONCreator;
|
||||
this.locale = locale;
|
||||
this.formatters = formatters;
|
||||
}
|
||||
@ -140,12 +147,34 @@ public class QueryJSONResolver implements Resolver {
|
||||
|
||||
Database database = dbSystem.getDatabase();
|
||||
return Maps.builder(String.class, Object.class)
|
||||
.put("players", new PlayersTableJSONCreator(
|
||||
database.query(new QueryTablePlayersQuery(playerUUIDs, after, before, config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD))),
|
||||
Collections.emptyMap(),
|
||||
config.get(DisplaySettings.OPEN_PLAYER_LINKS_IN_NEW_TAB),
|
||||
formatters, locale
|
||||
).toJSONMap())
|
||||
.put("players", getPlayersTableData(playerUUIDs, after, before))
|
||||
.put("activity", getActivityGraphData(playerUUIDs, after, before))
|
||||
.build();
|
||||
}
|
||||
|
||||
private Map<String, Object> getActivityGraphData(Set<UUID> playerUUIDs, long after, long before) {
|
||||
Database database = dbSystem.getDatabase();
|
||||
Long threshold = config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD);
|
||||
|
||||
long twoMonthsBeforeLastDate = before - TimeAmount.MONTH.toMillis(2L);
|
||||
long stopDate = Math.max(twoMonthsBeforeLastDate, after);
|
||||
|
||||
DateMap<Map<String, Integer>> activityData = new DateMap<>();
|
||||
for (long time = before; time >= stopDate; time -= TimeAmount.WEEK.toMillis(1L)) {
|
||||
activityData.put(time, database.query(NetworkActivityIndexQueries.fetchActivityIndexGroupingsOn(time, threshold, playerUUIDs)));
|
||||
}
|
||||
|
||||
Map<String, Object> activityGraphJSON = graphJSONCreator.createActivityGraphJSON(activityData);
|
||||
return activityGraphJSON;
|
||||
}
|
||||
|
||||
private Map<String, Object> getPlayersTableData(Set<UUID> playerUUIDs, long after, long before) {
|
||||
Database database = dbSystem.getDatabase();
|
||||
return new PlayersTableJSONCreator(
|
||||
database.query(new QueryTablePlayersQuery(playerUUIDs, after, before, config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD))),
|
||||
Collections.emptyMap(),
|
||||
config.get(DisplaySettings.OPEN_PLAYER_LINKS_IN_NEW_TAB),
|
||||
formatters, locale
|
||||
).toJSONMap();
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import com.djrapitops.plan.storage.database.queries.Query;
|
||||
import com.djrapitops.plan.storage.database.queries.QueryStatement;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.SessionsTable;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.UsersTable;
|
||||
import org.apache.commons.text.TextStringBuilder;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
@ -162,6 +163,36 @@ public class NetworkActivityIndexQueries {
|
||||
};
|
||||
}
|
||||
|
||||
public static Query<Map<String, Integer>> fetchActivityIndexGroupingsOn(long date, long threshold, Collection<UUID> playerUUIDs) {
|
||||
String selectActivityIndex = selectActivityIndexSQL();
|
||||
|
||||
String selectIndexes = SELECT + "activity_index" +
|
||||
FROM + UsersTable.TABLE_NAME + " u" +
|
||||
LEFT_JOIN + '(' + selectActivityIndex + ") s on s." + SessionsTable.USER_UUID + "=u." + UsersTable.USER_UUID +
|
||||
WHERE + "u." + UsersTable.REGISTERED + "<=?" +
|
||||
AND + "u." + UsersTable.USER_UUID + " IN ('" +
|
||||
new TextStringBuilder().appendWithSeparators(playerUUIDs, "','").build() + "')";
|
||||
|
||||
return new QueryStatement<Map<String, Integer>>(selectIndexes) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
setSelectActivityIndexSQLParameters(statement, 1, threshold, date);
|
||||
statement.setLong(9, date);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Integer> processResults(ResultSet set) throws SQLException {
|
||||
Map<String, Integer> groups = new HashMap<>();
|
||||
while (set.next()) {
|
||||
double activityIndex = set.getDouble("activity_index");
|
||||
String group = ActivityIndex.getGroup(activityIndex);
|
||||
groups.put(group, groups.getOrDefault(group, 0) + 1);
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Query<Integer> countNewPlayersTurnedRegular(long after, long before, Long threshold) {
|
||||
String selectActivityIndex = selectActivityIndexSQL();
|
||||
|
||||
|
@ -303,19 +303,29 @@ function runQuery() {
|
||||
|
||||
renderDataResultScreen(json.data.players.data.length, json.view ? json.view : {});
|
||||
|
||||
// Set URL so that the query result can be shared
|
||||
window.history.replaceState({}, '', `${location.pathname}?timestamp=${json.timestamp}`);
|
||||
|
||||
// Player table
|
||||
$('.player-table').DataTable({
|
||||
responsive: true,
|
||||
columns: json.data.players.columns,
|
||||
data: json.data.players.data,
|
||||
order: [[5, "desc"]]
|
||||
})
|
||||
});
|
||||
|
||||
// Activity graphs
|
||||
const activity_data = json.data.activity;
|
||||
activityPie('activityPie', {
|
||||
name: 'Players', colorByPoint: true, data: activity_data.activity_pie_series
|
||||
});
|
||||
stackChart('activityStackGraph', activity_data.activity_labels, activity_data.activity_series, 'Players');
|
||||
|
||||
const activityIndexHeader = document.querySelector("#DataTables_Table_0 thead th:nth-of-type(2)");
|
||||
const lastSeenHeader = document.querySelector("#DataTables_Table_0 thead th:nth-of-type(6)");
|
||||
|
||||
activityIndexHeader.innerHTML += ` (${filterView.beforeDate})`
|
||||
document.querySelector("#activity-date").innerHTML = json.view.beforeDate;
|
||||
activityIndexHeader.innerHTML += ` (${json.view.beforeDate})`
|
||||
lastSeenHeader.innerHTML += ` (view)`
|
||||
});
|
||||
}
|
||||
@ -351,5 +361,28 @@ function renderDataResultScreen(resultCount, view) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xl-8 col-lg-8 col-sm-12">
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
|
||||
<h6 class="m-0 font-weight-bold col-black"><i
|
||||
class="fas fa-fw fa-chart-line col-amber"></i>
|
||||
Activity of matched players</h6>
|
||||
</div>
|
||||
<div class="chart-area" id="activityStackGraph"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xl-4 col-lg-4 col-sm-12">
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
|
||||
<h6 class="m-0 font-weight-bold col-black"><i
|
||||
class="fa fa-fw fa-users col-amber"></i>
|
||||
Activity on <span id="activity-date"></span></h6>
|
||||
</div>
|
||||
<div class="chart-area" id="activityPie"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
@ -316,8 +316,12 @@
|
||||
<!-- Page level plugins -->
|
||||
<script src="vendor/datatables/jquery.dataTables.min.js"></script>
|
||||
<script src="vendor/datatables/dataTables.bootstrap4.min.js"></script>
|
||||
<script src="./vendor/highcharts/highstock.js"></script>
|
||||
<script src="./vendor/highcharts/map.js"></script>
|
||||
<script src="./vendor/highcharts/world.js"></script>
|
||||
|
||||
<!-- Page level custom scripts -->
|
||||
<script src="./js/graphs.js"></script>
|
||||
<script src='./js/query.js'></script>
|
||||
|
||||
<script id="mainScript">
|
||||
|
Loading…
Reference in New Issue
Block a user