diff --git a/.gitignore b/.gitignore index b55c258fa..c72e974fc 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ /ProjectHelper/nbproject/ /ProjectHelper/target/ /Filetool/nbproject/private/ -/Filetool/build/ \ No newline at end of file +/Filetool/build/ +/PlanPluginBridge/target/ \ No newline at end of file diff --git a/Plan/dependency-reduced-pom.xml b/Plan/dependency-reduced-pom.xml index 1315e729c..4dbd50b76 100644 --- a/Plan/dependency-reduced-pom.xml +++ b/Plan/dependency-reduced-pom.xml @@ -1,82 +1,127 @@ - 4.0.0 - com.djrapitops - Plan - 2.0.0 - - ${basedir}/src - clean package install - - - . - ${basedir}/src/main/resources - - *.yml - *.html - - - - ${project.name} - - - maven-compiler-plugin - 3.3 - - 1.8 - 1.8 - - - - maven-jar-plugin - 2.6 - - - maven-shade-plugin - 2.3 - - - package - - shade - - - - - - - org.jfree:* - - - - - org.jfree - com.djrapitops.plan.jfree - - - false - - - - - - - org.bukkit - craftbukkit - 1.10.2-R0.1-SNAPSHOT - provided - - - com.djrapitops - plan.lite - 1.6.3 - provided - - - - 1.8 - UTF-8 - 1.8 - + 4.0.0 + com.djrapitops + Plan + 3.4.3 + + ${basedir}/src + clean package install + + + . + ${basedir}/src/main/resources + + *.yml + *.html + + + + ${project.name} + + + maven-compiler-plugin + 3.3 + + 1.8 + 1.8 + + + + maven-shade-plugin + 2.4.3 + + + package + + shade + + + + + + + *:* + + org/** + javassist/** + mockito-extensions/** + net/** + junit/** + com/thoughtworks/** + + + + + + + maven-jar-plugin + 2.6 + + + **/test/* + **/*/test/* + **/*/test.* + **/test/**/* + + + + + org.pitest + pitest-maven + 1.1.8 + + + main.java.com.djrapitops.plan.* + + + test.java.main.java.com.djrapitops.plan.* + + 1000 + + + + maven-checkstyle-plugin + 2.17 + + **/test/**/* + checkstyle.xml + + + + maven-javadoc-plugin + 2.10.4 + + test.* + + + + + + + org.bukkit + craftbukkit + 1.11.2-R0.1-SNAPSHOT + provided + + + org.powermock + powermock + 1.6.6 + pom + compile + + + org.hamcrest + hamcrest-core + 1.3 + test + + + + 1.8 + UTF-8 + 1.8 + diff --git a/Plan/pom.xml b/Plan/pom.xml index 381f9c531..2ac7bb6f9 100644 --- a/Plan/pom.xml +++ b/Plan/pom.xml @@ -3,18 +3,8 @@ 4.0.0 com.djrapitops Plan - 3.4.2 + 3.4.3 jar - - - - vault-repo - http://nexus.hc.to/content/repositories/pub_releases - - org.bukkit @@ -24,58 +14,10 @@ - com.hm - advanced.achievements - 5.2 - provided - - - me.edge209 - ontime - 4.1.4 - provided - - - com.earth2me - essentials - 2.0.1 - provided - - - com.massivecraft - factions - 2.10.0 - provided - - - com.gamingmesh - jobs - 3.9.1 - provided - - - com.massivecraft - mcore - 2.10.0 - provided - - - com.gmail.nossr50 - mcmmo - 1.5.07 - provided - - - com.palmergames - towny - 0.91.4.0 - provided - - - net.milkbowl.vault - VaultAPI - 1.6 - provided + com.djrapitops + PlanPluginBridge + 3.4.3 + compile @@ -158,6 +100,34 @@ 1.8 + + org.apache.maven.plugins + maven-shade-plugin + 2.4.3 + + + package + + shade + + + + + + + *:* + + org/** + javassist/** + mockito-extensions/** + net/** + junit/** + com/thoughtworks/** + + + + + org.apache.maven.plugins maven-jar-plugin diff --git a/Plan/src/main/java/com/djrapitops/plan/Settings.java b/Plan/src/main/java/com/djrapitops/plan/Settings.java index 9b51127fd..112284307 100644 --- a/Plan/src/main/java/com/djrapitops/plan/Settings.java +++ b/Plan/src/main/java/com/djrapitops/plan/Settings.java @@ -34,6 +34,7 @@ public enum Settings { ENABLED_ONT("Customization.Plugins.Enabled.OnTime"), ENABLED_TOW("Customization.Plugins.Enabled.Towny"), ENABLED_VAU("Customization.Plugins.Enabled.Vault"), + LINK_PROTOCOL("Settings.WebServer.LinkProtocol"), // Integer ANALYSIS_MINUTES_FOR_ACTIVE("Settings.Analysis.MinutesPlayedUntilConsidiredActive"), SAVE_CACHE_MIN("Settings.Cache.DataCache.SaveEveryXMinutes"), @@ -61,6 +62,7 @@ public enum Settings { // FORMAT_YEAR("Customization.Formats.TimeAmount.Year"), FORMAT_YEARS("Customization.Formats.TimeAmount.Years"), + FORMAT_DAY("Customization.Formats.TimeAmount.Day"), FORMAT_DAYS("Customization.Formats.TimeAmount.Days"), FORMAT_HOURS("Customization.Formats.TimeAmount.Hours"), FORMAT_MINUTES("Customization.Formats.TimeAmount.Minutes"), diff --git a/Plan/src/main/java/com/djrapitops/plan/api/API.java b/Plan/src/main/java/com/djrapitops/plan/api/API.java index f42c1df65..ae465c0d0 100644 --- a/Plan/src/main/java/com/djrapitops/plan/api/API.java +++ b/Plan/src/main/java/com/djrapitops/plan/api/API.java @@ -83,7 +83,7 @@ public class API { * @return ip:port/security/player/Playername */ public String getPlayerInspectPageLink(String name) { - return HtmlUtils.getInspectUrl(name); + return HtmlUtils.getInspectUrlWithProtocol(name); } /** diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/AnalyzeCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/AnalyzeCommand.java index c9c926129..c9b50b8eb 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/AnalyzeCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/AnalyzeCommand.java @@ -90,7 +90,7 @@ public class AnalyzeCommand extends SubCommand { sender.sendMessage(TextUI.getAnalysisMessages()); } else { // Link - String url = HtmlUtils.getServerAnalysisUrl(); + String url = HtmlUtils.getServerAnalysisUrlWithProtocol(); String message = Phrase.CMD_LINK + ""; boolean console = !(sender instanceof Player); if (console) { diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/InspectCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/InspectCommand.java index 5ea81e3c7..c5e87fbb6 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/InspectCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/InspectCommand.java @@ -101,7 +101,7 @@ public class InspectCommand extends SubCommand { sender.sendMessage(TextUI.getInspectMessages(uuid)); } else { // Link - String url = HtmlUtils.getInspectUrl(playerName); + String url = HtmlUtils.getInspectUrlWithProtocol(playerName); String message = Phrase.CMD_LINK + ""; boolean console = !(sender instanceof Player); if (console) { diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/SearchCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/SearchCommand.java index b59af8657..ee3ab0483 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/SearchCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/SearchCommand.java @@ -81,7 +81,7 @@ public class SearchCommand extends SubCommand { String name = match.getName(); sender.sendMessage(Phrase.CMD_MATCH + name); // Link - String url = HtmlUtils.getInspectUrl(name); + String url = HtmlUtils.getInspectUrlWithProtocol(name); String message = Phrase.CMD_LINK + ""; boolean console = !(sender instanceof Player); if (console) { diff --git a/Plan/src/main/java/com/djrapitops/plan/data/additional/AnalysisType.java b/Plan/src/main/java/com/djrapitops/plan/data/additional/AnalysisType.java index dd6cace5c..11d9d04df 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/additional/AnalysisType.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/additional/AnalysisType.java @@ -1,9 +1,5 @@ package main.java.com.djrapitops.plan.data.additional; -import main.java.com.djrapitops.plan.data.additional.advancedachievements.AdvancedAchievementsTable; -import main.java.com.djrapitops.plan.data.additional.factions.FactionsTable; -import main.java.com.djrapitops.plan.data.additional.towny.TownyTable; - /** * This class contains Enum values for different types of Analysis that can be * performed on values of PluginData. @@ -102,10 +98,6 @@ public enum AnalysisType { * * Can be used to add Tables, Images (for example maps) and other html * elements. - * - * @see AdvancedAchievementsTable - * @see FactionsTable - * @see TownyTable */ HTML; diff --git a/Plan/src/main/java/com/djrapitops/plan/data/additional/HookHandler.java b/Plan/src/main/java/com/djrapitops/plan/data/additional/HookHandler.java index 8e949a783..34941969c 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/additional/HookHandler.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/additional/HookHandler.java @@ -1,7 +1,6 @@ package main.java.com.djrapitops.plan.data.additional; -import main.java.com.djrapitops.plan.data.additional.essentials.EssentialsHook; -import main.java.com.djrapitops.plan.data.additional.advancedachievements.AdvancedAchievementsHook; +import com.djrapitops.pluginbridge.plan.Bridge; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -10,13 +9,6 @@ import java.util.Map; import java.util.UUID; import java.util.stream.Collectors; import main.java.com.djrapitops.plan.Log; -import main.java.com.djrapitops.plan.Settings; -import main.java.com.djrapitops.plan.data.additional.factions.FactionsHook; -import main.java.com.djrapitops.plan.data.additional.jobs.JobsHook; -import main.java.com.djrapitops.plan.data.additional.mcmmo.McmmoHook; -import main.java.com.djrapitops.plan.data.additional.ontime.OnTimeHook; -import main.java.com.djrapitops.plan.data.additional.towny.TownyHook; -import main.java.com.djrapitops.plan.data.additional.vault.VaultHook; import main.java.com.djrapitops.plan.utilities.HtmlUtils; /** @@ -35,7 +27,12 @@ public class HookHandler { */ public HookHandler() { additionalDataSources = new ArrayList<>(); - hook(); + try { + Bridge.hook(this); + } catch (Throwable e) { + Log.toLog(this.getClass().getName(), e); + Log.error("Plan Plugin Bridge not included in the plugin jar."); + } } /** @@ -62,57 +59,6 @@ public class HookHandler { return additionalDataSources; } - private void hook() { - try { - if (Settings.ENABLED_AA.isTrue()) { - AdvancedAchievementsHook advancedAchievementsHook = new AdvancedAchievementsHook(this); - } - } catch (NoClassDefFoundError e) { - } - try { - if (Settings.ENABLED_ESS.isTrue()) { - EssentialsHook essentialsHook = new EssentialsHook(this); - } - } catch (NoClassDefFoundError e) { - } - try { - if (Settings.ENABLED_FAC.isTrue()) { - FactionsHook factionsHook = new FactionsHook(this); - } - } catch (NoClassDefFoundError e) { - } - try { - if (Settings.ENABLED_MCM.isTrue()) { - McmmoHook mcMmoHook = new McmmoHook(this); - } - } catch (NoClassDefFoundError e) { - } - try { - if (Settings.ENABLED_JOB.isTrue()) { - JobsHook jobsHook = new JobsHook(this); - } - } catch (NoClassDefFoundError e) { - } - try { - if (Settings.ENABLED_ONT.isTrue()) { - OnTimeHook onTimeHook = new OnTimeHook(this); - } - } catch (NoClassDefFoundError e) { - } - try { - if (Settings.ENABLED_TOW.isTrue()) { - TownyHook townyHook = new TownyHook(this); - } - } catch (NoClassDefFoundError e) { - } - try { - if (Settings.ENABLED_VAU.isTrue()) { - VaultHook vaultHook = new VaultHook(this); - } - } catch (NoClassDefFoundError e) { - } - } - /** * Used to get the Layout with PluginData placeholders to replace %plugins% * placeholder on analysis.hmtl. diff --git a/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheClearQueue.java b/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheClearQueue.java index 0cc2683a0..6d5c542f5 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheClearQueue.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/cache/queue/DataCacheClearQueue.java @@ -4,6 +4,7 @@ import java.util.Collection; import java.util.UUID; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; +import java.util.stream.Collectors; import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Phrase; import main.java.com.djrapitops.plan.Settings; @@ -47,6 +48,7 @@ public class DataCacheClearQueue extends Queue{ if (uuids.isEmpty()) { return; } + uuids = uuids.stream().filter(u -> u != null).collect(Collectors.toList()); Log.debug("Scheduling for clear: " + uuids); try { queue.addAll(uuids); diff --git a/Plan/src/main/java/com/djrapitops/plan/data/handling/importing/ImportUtils.java b/Plan/src/main/java/com/djrapitops/plan/data/handling/importing/ImportUtils.java index ee0d948e9..627940c0d 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/handling/importing/ImportUtils.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/handling/importing/ImportUtils.java @@ -1,7 +1,10 @@ package main.java.com.djrapitops.plan.data.handling.importing; +import com.djrapitops.pluginbridge.plan.Bridge; +import com.djrapitops.pluginbridge.plan.importing.OnTimeImporter; import java.util.HashMap; import java.util.Map; +import main.java.com.djrapitops.plan.Log; import static org.bukkit.Bukkit.getPluginManager; /** @@ -29,7 +32,13 @@ public class ImportUtils { */ public static Map getImporters() { Map importers = new HashMap<>(); - importers.put("ontime", new OnTimeImporter()); + try { + importers.put("ontime", new OnTimeImporter()); + } catch (Throwable e) { + Log.toLog("ImportUtils.getImporters", e); + Log.error("Plan Plugin Bridge not included in the plugin jar."); + } + return importers; } } diff --git a/Plan/src/main/java/com/djrapitops/plan/database/tables/UsersTable.java b/Plan/src/main/java/com/djrapitops/plan/database/tables/UsersTable.java index 1843dc459..4a708472c 100644 --- a/Plan/src/main/java/com/djrapitops/plan/database/tables/UsersTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/database/tables/UsersTable.java @@ -751,7 +751,9 @@ public class UsersTable extends Table { continue; } if (!savedUUIDs.contains(uuid)) { - saveLast.add(uData); + if (!saveLast.contains(uData)) { + saveLast.add(uData); + } continue; } uData.access(); diff --git a/Plan/src/main/java/com/djrapitops/plan/ui/webserver/Response.java b/Plan/src/main/java/com/djrapitops/plan/ui/webserver/Response.java index e384eb118..ca9cb77f0 100644 --- a/Plan/src/main/java/com/djrapitops/plan/ui/webserver/Response.java +++ b/Plan/src/main/java/com/djrapitops/plan/ui/webserver/Response.java @@ -49,13 +49,15 @@ public class Response { Log.debug("Request: " + requestUri); String[] requestArgs = requestUri.split("/"); boolean forbidden = false; - String securityCode = ""; + String givenCode = ""; + String securityCode = Settings.SECURITY_CODE + ""; if (requestArgs.length <= 2) { forbidden = true; } else { - securityCode = requestArgs[1]; + givenCode = requestArgs[1]; } - if (!securityCode.equals(Settings.SECURITY_CODE + "")) { + + if (!givenCode.equals(securityCode)) { forbidden = true; } if (forbidden) { diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/FormatUtils.java b/Plan/src/main/java/com/djrapitops/plan/utilities/FormatUtils.java index 3ad9b1ca2..4a8e70258 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/FormatUtils.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/FormatUtils.java @@ -106,18 +106,34 @@ public class FormatUtils { } } if (days != 0) { - builder.append(Settings.FORMAT_DAYS.toString().replace("%days%", "" + days)); + if (days == 1) { + builder.append(Settings.FORMAT_DAY.toString()); + } else { + builder.append(Settings.FORMAT_DAYS.toString().replace("%days%", "" + days)); + } } if (hours != 0) { - builder.append(Settings.FORMAT_HOURS.toString().replace("%hours%", "" + hours)); + String h = Settings.FORMAT_HOURS.toString().replace("%hours%", "" + hours); + if (h.contains("%zero%") && (hours+"").length() == 1) { + builder.append('0'); + } + builder.append(h); } if (minutes != 0) { - builder.append(Settings.FORMAT_MINUTES.toString().replace("%minutes%", "" + minutes)); + String m = Settings.FORMAT_MINUTES.toString().replace("%minutes%", "" + minutes); + if (m.contains("%zero%") && (minutes+"").length() == 1) { + builder.append('0'); + } + builder.append(m); } - if (seconds != 0) { - builder.append(Settings.FORMAT_SECONDS.toString().replace("%seconds%", "" + seconds)); + if (seconds != 0) { + String s = Settings.FORMAT_SECONDS.toString().replace("%seconds%", "" + seconds); + if (s.contains("%zero%") && (seconds+"").length() == 1) { + builder.append('0'); + } + builder.append(s); } - String formattedTime = builder.toString(); + String formattedTime = builder.toString().replace("%zero%", ""); if (formattedTime.isEmpty()) { return Settings.FORMAT_SECONDS.toString().replace("%seconds%", "0"); } diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/HtmlUtils.java b/Plan/src/main/java/com/djrapitops/plan/utilities/HtmlUtils.java index 2947a7c63..8c3c0d9f0 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/HtmlUtils.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/HtmlUtils.java @@ -49,6 +49,10 @@ public class HtmlUtils { return html; } + public static String getServerAnalysisUrlWithProtocol() { + return Settings.LINK_PROTOCOL.toString()+getServerAnalysisUrl(); + } + /** * * @return @@ -61,10 +65,14 @@ public class HtmlUtils { if (useAlternativeIP) { ip = Settings.ALTERNATIVE_IP.toString().replaceAll("%port%", "" + port); } - String url = "http://" + ip + "/" + securityCode + "/server"; + String url = /*"http:*/"//" + ip + "/" + securityCode + "/server"; return url; } + public static String getInspectUrlWithProtocol(String playerName) { + return Settings.LINK_PROTOCOL.toString()+getInspectUrl(playerName); + } + /** * * @param playerName @@ -78,7 +86,7 @@ public class HtmlUtils { if (useAlternativeIP) { ip = Settings.ALTERNATIVE_IP.toString().replaceAll("%port%", "" + port); } - String url = "http://" + ip + "/" + securityCode + "/player/" + playerName; + String url = /*"http:*/"//" + ip + "/" + securityCode + "/player/" + playerName; return url; } diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Analysis.java b/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Analysis.java index 7512750f7..5acf44865 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Analysis.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Analysis.java @@ -1,5 +1,6 @@ package main.java.com.djrapitops.plan.utilities.analysis; +import main.java.com.djrapitops.plan.data.additional.HookHandler; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -17,7 +18,6 @@ import main.java.com.djrapitops.plan.data.RawAnalysisData; import main.java.com.djrapitops.plan.data.SessionData; import main.java.com.djrapitops.plan.data.UserData; import main.java.com.djrapitops.plan.data.additional.AnalysisType; -import main.java.com.djrapitops.plan.data.additional.HookHandler; import main.java.com.djrapitops.plan.data.additional.PluginData; import main.java.com.djrapitops.plan.data.cache.AnalysisCacheHandler; import main.java.com.djrapitops.plan.data.cache.DataCacheHandler; @@ -164,7 +164,7 @@ public class Analysis { analysisCache.cache(analysisData); long time = Benchmark.stop("Analysis"); if (Settings.ANALYSIS_LOG_FINISHED.isTrue()) { - Log.info(Phrase.ANALYSIS_COMPLETE.parse(time + "", HtmlUtils.getServerAnalysisUrl())); + Log.info(Phrase.ANALYSIS_COMPLETE.parse(time + "", HtmlUtils.getServerAnalysisUrlWithProtocol())); } // LocationAnalysis.performAnalysis(analysisData, plugin.getDB()); ExportUtility.export(plugin, analysisData, rawData); diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/ExportUtility.java b/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/ExportUtility.java index 408b4de54..af2b06475 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/ExportUtility.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/ExportUtility.java @@ -1,8 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ package main.java.com.djrapitops.plan.utilities.analysis; import java.io.File; @@ -52,7 +47,7 @@ public class ExportUtility { Benchmark.start("Exporting Html pages"); try { File folder = getFolder(); - writeAnalysisHtml(analysisData, folder); + writeAnalysisHtml(analysisData, new File(folder, "server")); File playersFolder = getPlayersFolder(folder); for (UserData userData : rawData) { writeInspectHtml(userData, playersFolder); @@ -85,14 +80,14 @@ public class ExportUtility { Files.write(inspectHtmlFile.toPath(), Arrays.asList(inspectHtml)); } - public static void writeAnalysisHtml(AnalysisData analysisData, File folder) throws FileNotFoundException, IOException { + public static void writeAnalysisHtml(AnalysisData analysisData, File serverFolder) throws FileNotFoundException, IOException { if (!Settings.ANALYSIS_EXPORT.isTrue()) { return; } String analysisHtml = HtmlUtils.replacePlaceholders(HtmlUtils.getHtmlStringFromResource("analysis.html"), PlaceholderUtils.getAnalysisReplaceRules(analysisData)) .replace(HtmlUtils.getInspectUrl(""), "./player/"); - File analysisHtmlFile = new File(folder, "analysis.html"); + File analysisHtmlFile = new File(serverFolder, "index.html"); if (analysisHtmlFile.exists()) { analysisHtmlFile.delete(); } diff --git a/Plan/src/main/resources/analysis.html b/Plan/src/main/resources/analysis.html index d2510367f..290a2b165 100644 --- a/Plan/src/main/resources/analysis.html +++ b/Plan/src/main/resources/analysis.html @@ -282,7 +282,7 @@ header p {
- Player Analytics | Analysis + Player Analytics | Analysis

Player Analytics v.%version%

%servername% | Server Analysis

@@ -857,7 +857,7 @@ function countUpTimer() { setTimeout('countUpTimer()', 1000); } - + - +