mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-15 05:41:51 +08:00
Made online activity overview update again on load
This commit is contained in:
parent
6b4fb12755
commit
b8ec15e381
@ -104,8 +104,16 @@ public class AsyncJSONResolverService {
|
||||
} else {
|
||||
// If there is no version available, block thread until the new finishes being generated.
|
||||
try {
|
||||
// updatedJSON is not null in this case ever because previousUpdates.getOrDefault(..., 0L) gets 0.
|
||||
//noinspection ConstantConditions
|
||||
// Can be null if the last update was recent and the file is deleted before next update
|
||||
if (updatedJSON == null) {
|
||||
updatedJSON = processing.submitNonCritical(() -> {
|
||||
JSONStorage.StoredJSON created = jsonStorage.storeJson(identifier, creator.apply(serverUUID));
|
||||
currentlyProcessing.remove(identifier);
|
||||
jsonStorage.invalidateOlder(identifier, created.timestamp);
|
||||
previousUpdates.put(identifier, created.timestamp);
|
||||
return created;
|
||||
}); // TODO Refactor this spaghetti code
|
||||
}
|
||||
return updatedJSON.get();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
@ -157,8 +165,16 @@ public class AsyncJSONResolverService {
|
||||
} else {
|
||||
// If there is no version available, block thread until the new finishes being generated.
|
||||
try {
|
||||
// updatedJSON is not null in this case ever because previousUpdates.getOrDefault(..., 0L) gets 0.
|
||||
//noinspection ConstantConditions
|
||||
// Can be null if the last update was recent and the file is deleted before next update.
|
||||
if (updatedJSON == null) {
|
||||
updatedJSON = processing.submitNonCritical(() -> {
|
||||
JSONStorage.StoredJSON created = jsonStorage.storeJson(identifier, creator.get());
|
||||
currentlyProcessing.remove(identifier);
|
||||
jsonStorage.invalidateOlder(identifier, created.timestamp);
|
||||
previousUpdates.put(identifier, created.timestamp);
|
||||
return created;
|
||||
}); // TODO Refactor this spaghetti code
|
||||
}
|
||||
return updatedJSON.get();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
|
@ -131,6 +131,7 @@ public enum HtmlLang implements Lang {
|
||||
SIDE_PVP_PVE("PvP & PvE"),
|
||||
SIDE_PERFORMANCE("Performance"),
|
||||
LABEL_RETENTION("New Player Retention"),
|
||||
DESCRIBE_RETENTION_PREDICTION("This value is a prediction based on previous players."),
|
||||
TITLE_SERVER_AS_NUMBERS("Server as Numbers"),
|
||||
TITLE_ONLINE_ACTIVITY_AS_NUMBERS("Online Activity as Numbers"),
|
||||
COMPARING_15_DAYS("Comparing 15 days"),
|
||||
|
@ -27,6 +27,7 @@ import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
import com.djrapitops.plugin.logging.debug.DebugLogger;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -81,13 +82,33 @@ public class JSONFileStorage implements JSONStorage {
|
||||
@Override
|
||||
public StoredJSON storeJson(String identifier, String json, long timestamp) {
|
||||
Path writingTo = jsonDirectory.resolve(identifier + '-' + timestamp + JSON_FILE_EXTENSION);
|
||||
String jsonToWrite = addMissingTimestamp(json, timestamp);
|
||||
try {
|
||||
Files.createDirectories(jsonDirectory);
|
||||
Files.write(writingTo, json.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE);
|
||||
Files.write(writingTo, jsonToWrite.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE);
|
||||
} catch (IOException e) {
|
||||
logger.warn("Could not write a file to " + writingTo.toFile().getAbsolutePath() + ": " + e.getMessage());
|
||||
}
|
||||
return new StoredJSON(json, timestamp, dateFormatter);
|
||||
return new StoredJSON(jsonToWrite, timestamp);
|
||||
}
|
||||
|
||||
private String addMissingTimestamp(String json, long timestamp) {
|
||||
String writtenJSON;
|
||||
if (!json.startsWith("{\"") || json.contains("timestamp")) {
|
||||
if (!json.contains("timestamp_f")) {
|
||||
writtenJSON = StringUtils.replaceOnce(json,
|
||||
"\"timestamp\"",
|
||||
"\"timestamp_f\":\"" + dateFormatter.apply(timestamp) + "\",\"timestamp\""
|
||||
);
|
||||
} else {
|
||||
writtenJSON = json;
|
||||
}
|
||||
} else {
|
||||
writtenJSON = "{\"timestamp\": " + timestamp +
|
||||
",\"timestamp_f\":\"" + dateFormatter.apply(timestamp) +
|
||||
"\",\"" + json.substring(2);
|
||||
}
|
||||
return writtenJSON;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -110,7 +131,7 @@ public class JSONFileStorage implements JSONStorage {
|
||||
long timestamp = Long.parseLong(timestampMatch.group(1));
|
||||
StringBuilder json = new StringBuilder();
|
||||
lines.forEach(json::append);
|
||||
return new StoredJSON(json.toString(), timestamp, dateFormatter);
|
||||
return new StoredJSON(json.toString(), timestamp);
|
||||
} catch (IOException e) {
|
||||
logger.warn(jsonDirectory.toFile().getAbsolutePath() + " file '" + from.getName() + "' could not be read: " + e.getMessage());
|
||||
} catch (NumberFormatException e) {
|
||||
|
@ -17,7 +17,6 @@
|
||||
package com.djrapitops.plan.storage.json;
|
||||
|
||||
import com.djrapitops.plan.SubSystem;
|
||||
import com.djrapitops.plan.delivery.formatting.Formatter;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import java.util.Objects;
|
||||
@ -66,14 +65,8 @@ public interface JSONStorage extends SubSystem {
|
||||
public final String json;
|
||||
public final long timestamp;
|
||||
|
||||
public StoredJSON(String json, long timestamp, Formatter<Long> dateFormatter) {
|
||||
if (!json.startsWith("{\"") || json.contains("timestamp")) {
|
||||
this.json = json;
|
||||
} else {
|
||||
this.json = "{\"timestamp\": " + timestamp +
|
||||
",\"timestamp_f\":\"" + dateFormatter.apply(timestamp) +
|
||||
"\",\"" + json.substring(2);
|
||||
}
|
||||
public StoredJSON(String json, long timestamp) {
|
||||
this.json = json;
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
|
@ -1257,4 +1257,8 @@ body.sidebar-hidden .navbar-nav {
|
||||
.refresh-element {
|
||||
font-size: 1rem;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.refresh-element > i {
|
||||
cursor: pointer;
|
||||
}
|
@ -123,62 +123,62 @@ function loadserverOverviewValues(json, error) {
|
||||
|
||||
/* This function loads Online Activity Overview tab */
|
||||
function loadOnlineActivityOverviewValues(json, error) {
|
||||
tab = $('#online-activity-overview');
|
||||
const tab = document.getElementById('online-activity-overview');
|
||||
|
||||
if (error) {
|
||||
displayError(tab, error);
|
||||
displayError($('#online-activity-overview'), error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Online Activity as Numbers
|
||||
data = json.numbers;
|
||||
element = $(tab).find('#data_numbers');
|
||||
let data = json.numbers;
|
||||
let element = tab.querySelector('#data_numbers');
|
||||
|
||||
$(element).find('#data_unique_players_30d').replaceWith('<td>' + data.unique_players_30d + smallTrend(data.unique_players_30d_trend) + '</td>');
|
||||
$(element).find('#data_unique_players_7d').text(data.unique_players_7d);
|
||||
$(element).find('#data_unique_players_24h').text(data.unique_players_24h);
|
||||
element.querySelector('#data_unique_players_30d').innerHTML = data.unique_players_30d + smallTrend(data.unique_players_30d_trend);
|
||||
element.querySelector('#data_unique_players_7d').innerText = data.unique_players_7d;
|
||||
element.querySelector('#data_unique_players_24h').innerText = data.unique_players_24h;
|
||||
|
||||
$(element).find('#data_unique_players_30d_avg').replaceWith('<td>' + data.unique_players_30d_avg + smallTrend(data.unique_players_30d_avg_trend) + '</td>');
|
||||
$(element).find('#data_unique_players_7d_avg').text(data.unique_players_7d_avg);
|
||||
$(element).find('#data_unique_players_24h_avg').text(data.unique_players_24h_avg);
|
||||
element.querySelector('#data_unique_players_30d_avg').innerHTML = data.unique_players_30d_avg + smallTrend(data.unique_players_30d_avg_trend);
|
||||
element.querySelector('#data_unique_players_7d_avg').innerText = data.unique_players_7d_avg;
|
||||
element.querySelector('#data_unique_players_24h_avg').innerText = data.unique_players_24h_avg;
|
||||
|
||||
$(element).find('#data_new_players_30d').replaceWith('<td>' + data.new_players_30d + smallTrend(data.new_players_30d_trend) + '</td>');
|
||||
$(element).find('#data_new_players_7d').text(data.new_players_7d);
|
||||
$(element).find('#data_new_players_24h').text(data.new_players_24h);
|
||||
element.querySelector('#data_new_players_30d').innerHTML = data.new_players_30d + smallTrend(data.new_players_30d_trend);
|
||||
element.querySelector('#data_new_players_7d').innerText = data.new_players_7d;
|
||||
element.querySelector('#data_new_players_24h').innerText = data.new_players_24h;
|
||||
|
||||
$(element).find('#data_new_players_30d_avg').replaceWith('<td>' + data.new_players_30d_avg + smallTrend(data.new_players_30d_avg_trend) + '</td>');
|
||||
$(element).find('#data_new_players_7d_avg').text(data.new_players_7d_avg);
|
||||
$(element).find('#data_new_players_24h_avg').text(data.new_players_24h_avg);
|
||||
element.querySelector('#data_new_players_30d_avg').innerHTML = data.new_players_30d_avg + smallTrend(data.new_players_30d_avg_trend);
|
||||
element.querySelector('#data_new_players_7d_avg').innerText = data.new_players_7d_avg;
|
||||
element.querySelector('#data_new_players_24h_avg').innerText = data.new_players_24h_avg;
|
||||
|
||||
$(element).find('#data_new_players_retention_30d').text('(' + data.new_players_retention_30d + '/' + data.new_players_30d + ') ' + data.new_players_retention_30d_perc);
|
||||
$(element).find('#data_new_players_retention_7d').text('(' + data.new_players_retention_7d + '/' + data.new_players_7d + ') ' + data.new_players_retention_7d_perc);
|
||||
$(element).find('#data_new_players_retention_24h').replaceWith(`<td title="This value is a prediction based on previous players.">(` + data.new_players_retention_24h + '/' + data.new_players_24h + ') ' + data.new_players_retention_24h_perc + ' <i class="far fa-fw fa-eye"></i></td>');
|
||||
element.querySelector('#data_new_players_retention_30d').innerText = '(' + data.new_players_retention_30d + '/' + data.new_players_30d + ') ' + data.new_players_retention_30d_perc;
|
||||
element.querySelector('#data_new_players_retention_7d').innerText = '(' + data.new_players_retention_7d + '/' + data.new_players_7d + ') ' + data.new_players_retention_7d_perc;
|
||||
element.querySelector('#data_new_players_retention_24h').innerHTML = '(' + data.new_players_retention_24h + '/' + data.new_players_24h + ') ' + data.new_players_retention_24h_perc + ' <i class="far fa-fw fa-eye"></i>';
|
||||
|
||||
$(element).find('#data_playtime_30d').replaceWith('<td>' + data.playtime_30d + smallTrend(data.playtime_30d_trend) + '</td>');
|
||||
$(element).find('#data_playtime_7d').text(data.playtime_7d);
|
||||
$(element).find('#data_playtime_24h').text(data.playtime_24h);
|
||||
element.querySelector('#data_playtime_30d').innerHTML = data.playtime_30d + smallTrend(data.playtime_30d_trend);
|
||||
element.querySelector('#data_playtime_7d').innerText = data.playtime_7d;
|
||||
element.querySelector('#data_playtime_24h').innerText = data.playtime_24h;
|
||||
|
||||
$(element).find('#data_playtime_30d_avg').replaceWith('<td>' + data.playtime_30d_avg + smallTrend(data.playtime_30d_avg_trend) + '</td>');
|
||||
$(element).find('#data_playtime_7d_avg').text(data.playtime_7d_avg);
|
||||
$(element).find('#data_playtime_24h_avg').text(data.playtime_24h_avg);
|
||||
element.querySelector('#data_playtime_30d_avg').innerHTML = data.playtime_30d_avg + smallTrend(data.playtime_30d_avg_trend);
|
||||
element.querySelector('#data_playtime_7d_avg').innerText = data.playtime_7d_avg;
|
||||
element.querySelector('#data_playtime_24h_avg').innerText = data.playtime_24h_avg;
|
||||
|
||||
$(element).find('#data_session_length_30d_avg').replaceWith('<td>' + data.session_length_30d_avg + smallTrend(data.session_length_30d_trend) + '</td>');
|
||||
$(element).find('#data_session_length_7d_avg').text(data.session_length_7d_avg);
|
||||
$(element).find('#data_session_length_24h_avg').text(data.session_length_24h_avg);
|
||||
element.querySelector('#data_session_length_30d_avg').innerHTML = data.session_length_30d_avg + smallTrend(data.session_length_30d_trend);
|
||||
element.querySelector('#data_session_length_7d_avg').innerText = data.session_length_7d_avg;
|
||||
element.querySelector('#data_session_length_24h_avg').innerText = data.session_length_24h_avg;
|
||||
|
||||
$(element).find('#data_sessions_30d').replaceWith('<td>' + data.sessions_30d + smallTrend(data.sessions_30d_trend) + '</td>');
|
||||
$(element).find('#data_sessions_7d').text(data.sessions_7d);
|
||||
$(element).find('#data_sessions_24h').text(data.sessions_24h);
|
||||
element.querySelector('#data_sessions_30d').innerHTML = data.sessions_30d + smallTrend(data.sessions_30d_trend);
|
||||
element.querySelector('#data_sessions_7d').innerText = data.sessions_7d;
|
||||
element.querySelector('#data_sessions_24h').innerText = data.sessions_24h;
|
||||
|
||||
// Insights
|
||||
data = json.insights;
|
||||
element = $(tab).find('#data_insights');
|
||||
element = tab.querySelector('#data_insights');
|
||||
|
||||
$(element).find('#data_players_first_join_avg').replaceWith(data.players_first_join_avg + smallTrend(data.players_first_join_trend));
|
||||
$(element).find('#data_first_session_length_avg').replaceWith(data.first_session_length_avg + smallTrend(data.first_session_length_trend));
|
||||
$(element).find('#data_first_session_length_median').replaceWith(data.first_session_length_median + smallTrend(data.first_session_length_median_trend));
|
||||
$(element).find('#data_lone_joins').replaceWith(data.lone_joins + smallTrend(data.lone_joins_trend));
|
||||
$(element).find('#data_lone_new_joins').replaceWith(data.lone_new_joins + smallTrend(data.lone_new_joins_trend))
|
||||
element.querySelector('#data_players_first_join_avg').innerHTML = data.players_first_join_avg + smallTrend(data.players_first_join_trend);
|
||||
element.querySelector('#data_first_session_length_avg').innerHTML = data.first_session_length_avg + smallTrend(data.first_session_length_trend);
|
||||
element.querySelector('#data_first_session_length_median').innerHTML = data.first_session_length_median + smallTrend(data.first_session_length_median_trend);
|
||||
element.querySelector('#data_lone_joins').innerHTML = data.lone_joins + smallTrend(data.lone_joins_trend);
|
||||
element.querySelector('#data_lone_new_joins').innerHTML = data.lone_new_joins + smallTrend(data.lone_new_joins_trend);
|
||||
}
|
||||
|
||||
/* This function loads Sessions tab */
|
||||
|
@ -4,26 +4,35 @@ function refreshingJsonRequest(address, callback, tabID) {
|
||||
? `${address}×tamp=${timestamp}`
|
||||
: `${address}?timestamp=${timestamp}`
|
||||
|
||||
const refreshElement = document.querySelector(`#${tabID} .refresh-element`);
|
||||
refreshElement.querySelector('i').addEventListener('click', () => {
|
||||
refreshElement.querySelector('.refresh-notice').innerHTML = '<i class="fa fa-fw fa-cog fa-spin"></i> Updating..';
|
||||
refreshingJsonRequest(address, callback, tabID);
|
||||
});
|
||||
|
||||
let timeout = 1000;
|
||||
|
||||
function makeTheRequest() {
|
||||
jsonRequest(addressWithTimestamp, (json, error) => {
|
||||
const refreshElement = document.querySelector(`#${tabID} .refresh-element`);
|
||||
if (error) {
|
||||
if (error.status === 400 && error.error.includes('Attempt to get data from the future!')) {
|
||||
console.error(error.error); // System time not in sync with UTC
|
||||
refreshElement.innerHTML = "System times out of sync with UTC";
|
||||
return jsonRequest(address, callback);
|
||||
}
|
||||
refreshElement.querySelector('.refresh-notice').remove();
|
||||
refreshElement.querySelector('.refresh-notice').innerHTML = "";
|
||||
return callback(json, error);
|
||||
}
|
||||
|
||||
refreshElement.querySelector('.refresh-time').innerText = json.timestamp_f;
|
||||
|
||||
const lastUpdated = json.timestamp;
|
||||
// TODO Work out the kinks with the refresh barrier time
|
||||
if (lastUpdated < timestamp) {
|
||||
setTimeout(makeTheRequest, 5000);
|
||||
setTimeout(makeTheRequest, timeout);
|
||||
timeout = timeout >= 12000 ? timeout : timeout * 2;
|
||||
} else {
|
||||
refreshElement.querySelector('.refresh-notice').remove();
|
||||
refreshElement.querySelector('.refresh-notice').innerHTML = "";
|
||||
}
|
||||
callback(json, error);
|
||||
})
|
||||
|
@ -159,7 +159,7 @@
|
||||
<h1 class="h3 mb-0 text-gray-800"><i class="sidebar-toggler fa fa-fw fa-bars"></i>${serverDisplayName}
|
||||
· Server Overview
|
||||
<span class="refresh-element">
|
||||
<i class="far fa-fw fa-clock"></i> <span class="refresh-time"></span>
|
||||
<i class="fa fa-fw fa-sync"></i> <span class="refresh-time"></span>
|
||||
<span class="refresh-notice"><i class="fa fa-fw fa-cog fa-spin"></i> Updating..</span>
|
||||
</span>
|
||||
</h1>
|
||||
@ -333,7 +333,12 @@
|
||||
<!-- Page Heading -->
|
||||
<div class="d-sm-flex align-items-center justify-content-between mb-4">
|
||||
<h1 class="h3 mb-0 text-gray-800"><i class="sidebar-toggler fa fa-fw fa-bars"></i>${serverDisplayName}
|
||||
· Online Activity Overview</h1>
|
||||
· Online Activity Overview
|
||||
<span class="refresh-element">
|
||||
<i class="fa fa-fw fa-sync"></i> <span class="refresh-time"></span>
|
||||
<span class="refresh-notice"><i class="fa fa-fw fa-cog fa-spin"></i> Updating..</span>
|
||||
</span>
|
||||
</h1>
|
||||
${backButton}
|
||||
</div>
|
||||
|
||||
@ -451,7 +456,8 @@
|
||||
</td>
|
||||
<td id="data_new_players_retention_30d"></td>
|
||||
<td id="data_new_players_retention_7d"></td>
|
||||
<td id="data_new_players_retention_24h"></td>
|
||||
<td id="data_new_players_retention_24h"
|
||||
title="This value is a prediction based on previous players."></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody>
|
||||
@ -1296,7 +1302,7 @@
|
||||
try {
|
||||
setLoadingText('Calculating values..');
|
||||
refreshingJsonRequest("../v1/serverOverview?server=${serverUUID}", loadserverOverviewValues, 'server-overview');
|
||||
jsonRequest("../v1/onlineOverview?server=${serverUUID}", loadOnlineActivityOverviewValues);
|
||||
refreshingJsonRequest("../v1/onlineOverview?server=${serverUUID}", loadOnlineActivityOverviewValues, 'online-activity-overview');
|
||||
jsonRequest("../v1/sessionsOverview?server=${serverUUID}", loadSessionValues);
|
||||
jsonRequest("../v1/playerVersus?server=${serverUUID}", loadPvPPvEValues);
|
||||
jsonRequest("../v1/playerbaseOverview?server=${serverUUID}", loadPlayerbaseOverviewValues);
|
||||
|
Loading…
Reference in New Issue
Block a user