From a218e509bfcf53c40e055a40d19d0d08d7c40655 Mon Sep 17 00:00:00 2001 From: Rsl1122 Date: Tue, 25 Jul 2017 17:55:10 +0300 Subject: [PATCH 1/2] Fix #183 Now using scatter graph. Scatter graph removes duplicate Sessions before visualization Removed old unused PlayerGraph methods. Fix a catch for non existing exception. --- .../inspectionProfiles/Project_Default.xml | 29 +++++ .../commands/manage/ManageClearCommand.java | 4 - .../graphs/PlayerActivityGraphCreator.java | 102 +++--------------- .../ui/html/graphs/ScatterGraphCreator.java | 15 ++- .../plan/utilities/analysis/Point.java | 6 +- Plan/src/main/resources/player.html | 3 +- .../PlayerActivityGraphCreatorTest.java | 84 +++------------ 7 files changed, 74 insertions(+), 169 deletions(-) create mode 100644 Plan/.idea/inspectionProfiles/Project_Default.xml diff --git a/Plan/.idea/inspectionProfiles/Project_Default.xml b/Plan/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 000000000..b8f43165f --- /dev/null +++ b/Plan/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,29 @@ + + + + \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageClearCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageClearCommand.java index aeed2f017..4a4f9c6d7 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageClearCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageClearCommand.java @@ -5,7 +5,6 @@ import com.djrapitops.plugin.command.ISender; import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.utilities.Verify; -import java.sql.SQLException; import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Phrase; @@ -76,9 +75,6 @@ public class ManageClearCommand extends SubCommand { } else { sender.sendMessage(Phrase.MANAGE_PROCESS_FAIL + ""); } - } catch (SQLException e) { - Log.toLog(this.getClass().getName(), e); - sender.sendMessage(Phrase.MANAGE_PROCESS_FAIL + ""); } finally { this.cancel(); } diff --git a/Plan/src/main/java/com/djrapitops/plan/ui/html/graphs/PlayerActivityGraphCreator.java b/Plan/src/main/java/com/djrapitops/plan/ui/html/graphs/PlayerActivityGraphCreator.java index d35c7a1d6..959df1d1c 100644 --- a/Plan/src/main/java/com/djrapitops/plan/ui/html/graphs/PlayerActivityGraphCreator.java +++ b/Plan/src/main/java/com/djrapitops/plan/ui/html/graphs/PlayerActivityGraphCreator.java @@ -1,12 +1,13 @@ package main.java.com.djrapitops.plan.ui.html.graphs; +import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.data.SessionData; import main.java.com.djrapitops.plan.data.TPS; import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.analysis.Point; -import java.util.*; -import java.util.function.Function; +import java.util.Arrays; +import java.util.List; import java.util.stream.Collectors; /** @@ -26,100 +27,23 @@ public class PlayerActivityGraphCreator { public static String buildScatterDataStringSessions(List sessionData, long scale) { long now = MiscUtils.getTime(); long nowMinusScale = now - scale; - List> s = filterAndTransformSessions(sessionData, nowMinusScale); - List sessionStarts = s.get(0); - List sessionEnds = s.get(1); + List filtered = filterSessions(sessionData, nowMinusScale); - int amount = (int) sessionStarts.stream().filter(start -> start < nowMinusScale).count(); - for (int i = amount; i > 0; i--) { - sessionStarts.add(nowMinusScale); - } + List points = filtered.stream() + .map(session -> new Point[]{new Point(session.getSessionStart(), 1), new Point(session.getSessionEnd(), 0)}) + .flatMap(Arrays::stream) + .collect(Collectors.toList()); - Map changeMap = transformIntoChangeMap(sessionStarts, sessionEnds); - List points = getPointsFromChangeMap(changeMap); - return ScatterGraphCreator.scatterGraph(points, false); + Log.debug(points.stream().map(Point::getY).collect(Collectors.toList()).toString()); + return ScatterGraphCreator.scatterGraph(points, true, false); } - private static List getPointsFromChangeMap(Map changeMap) { - List points = new ArrayList<>(); - int lastIndex = -1; - int i = 0; - for (Long key : changeMap.keySet()) { - long date = key; - int change = changeMap.get(key); - if (change != 0) { - int previousValue = 0; - if (lastIndex >= 0) { - previousValue = (int) points.get(lastIndex).getY(); - } - points.add(new Point(date, previousValue+change)); - lastIndex = i; - i++; - } - } - return points; - } - - private static Map transformIntoChangeMap(List sessionStarts, List sessionEnds) { - Map starts = sessionStarts.stream().distinct().collect(Collectors.toMap(Function.identity(), start -> Collections.frequency(sessionStarts, start))); - Map ends = sessionEnds.stream().distinct().collect(Collectors.toMap(Function.identity(), end -> Collections.frequency(sessionEnds, end))); - Set keys = new HashSet<>(starts.keySet()); - keys.addAll(ends.keySet()); - Map change = new HashMap<>(); - keys.forEach((key) -> { - int value = 0; - if (starts.containsKey(key)) { - value += starts.get(key); - } - if (ends.containsKey(key)) { - value -= ends.get(key); - } - change.put(key, value); - }); - return change; - } - - /** - * @param values - * @param lookFor - * @return - */ - public static long getCount(List values, long lookFor) { - return Collections.frequency(values, lookFor); - } - - /** - * @param sessionData - * @param nowMinusScale - * @return - */ - public static List> filterAndTransformSessions(List sessionData, long nowMinusScale) { - List values = sessionData.parallelStream() + private static List filterSessions(List sessions, long nowMinusScale) { + return sessions.parallelStream() .filter(session -> (session != null)) .filter(session -> session.isValid() || session.getSessionEnd() == -1) .filter((session) -> (session.getSessionStart() >= nowMinusScale || session.getSessionEnd() >= nowMinusScale)) - .map(session -> new Long[]{session.getSessionStart(), session.getSessionEnd()}) + .distinct() .collect(Collectors.toList()); - List sessionStarts = new ArrayList<>(); - List sessionEnds = new ArrayList<>(); - for (Long[] startAndEnd : values) { - sessionStarts.add(getSecond(startAndEnd[0])); - Long end = startAndEnd[1]; - if (end != -1) { - sessionEnds.add(getSecond(end)); - } - } - List> r = new ArrayList<>(); - r.add(sessionStarts); - r.add(sessionEnds); - return r; - } - - /** - * @param ms - * @return - */ - public static long getSecond(long ms) { - return ms - (ms % 1000); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/ui/html/graphs/ScatterGraphCreator.java b/Plan/src/main/java/com/djrapitops/plan/ui/html/graphs/ScatterGraphCreator.java index 174020164..2f88c0b8b 100644 --- a/Plan/src/main/java/com/djrapitops/plan/ui/html/graphs/ScatterGraphCreator.java +++ b/Plan/src/main/java/com/djrapitops/plan/ui/html/graphs/ScatterGraphCreator.java @@ -7,15 +7,14 @@ package main.java.com.djrapitops.plan.ui.html.graphs; import com.djrapitops.plugin.api.TimeAmount; import com.djrapitops.plugin.utilities.Verify; +import main.java.com.djrapitops.plan.utilities.analysis.DouglasPeckerAlgorithm; +import main.java.com.djrapitops.plan.utilities.analysis.Point; +import main.java.com.djrapitops.plan.utilities.comparators.PointComparator; import java.util.HashSet; import java.util.List; import java.util.Set; -import main.java.com.djrapitops.plan.utilities.analysis.DouglasPeckerAlgorithm; -import main.java.com.djrapitops.plan.utilities.analysis.Point; -import main.java.com.djrapitops.plan.utilities.comparators.PointComparator; - /** * Abstract scatter graph creator used by other graph creators. * @@ -25,10 +24,16 @@ import main.java.com.djrapitops.plan.utilities.comparators.PointComparator; public class ScatterGraphCreator { public static String scatterGraph(List points, boolean reduceGapTriangles) { + return scatterGraph(points, reduceGapTriangles, true); + } + + public static String scatterGraph(List points, boolean reduceGapTriangles, boolean reducePoints) { StringBuilder arrayBuilder = new StringBuilder(); arrayBuilder.append("["); - points = DouglasPeckerAlgorithm.reducePoints(points, 0); + if (reducePoints) { + points = DouglasPeckerAlgorithm.reducePoints(points, 0); + } if (reduceGapTriangles) { Point lastPoint = null; diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Point.java b/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Point.java index a4aa0abf0..7ab5b495c 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Point.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Point.java @@ -1,7 +1,6 @@ package main.java.com.djrapitops.plan.utilities.analysis; /** - * * @author Rsl1122 * @since 3.5.2 */ @@ -21,4 +20,9 @@ public class Point { public double getY() { return y; } + + @Override + public String toString() { + return "{x:" + x + " y:" + y + '}'; + } } diff --git a/Plan/src/main/resources/player.html b/Plan/src/main/resources/player.html index 330fed5b0..3abb3da12 100644 --- a/Plan/src/main/resources/player.html +++ b/Plan/src/main/resources/player.html @@ -765,7 +765,8 @@ return ''; }; }, - suggestedMax: %graphmaxplayers% + suggestedMax: %graphmaxplayers%, + suggestedMin: 0 } }], xAxes: [{ diff --git a/Plan/src/test/java/main/java/com/djrapitops/plan/ui/graphs/PlayerActivityGraphCreatorTest.java b/Plan/src/test/java/main/java/com/djrapitops/plan/ui/graphs/PlayerActivityGraphCreatorTest.java index 539038e78..71d4c9587 100644 --- a/Plan/src/test/java/main/java/com/djrapitops/plan/ui/graphs/PlayerActivityGraphCreatorTest.java +++ b/Plan/src/test/java/main/java/com/djrapitops/plan/ui/graphs/PlayerActivityGraphCreatorTest.java @@ -1,8 +1,8 @@ package test.java.main.java.com.djrapitops.plan.ui.graphs; import main.java.com.djrapitops.plan.data.SessionData; -import main.java.com.djrapitops.plan.ui.html.graphs.PlayerActivityGraphCreator; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import java.util.ArrayList; @@ -10,11 +10,7 @@ import java.util.Date; import java.util.List; import java.util.Random; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - /** - * * @author Rsl1122 */ public class PlayerActivityGraphCreatorTest { @@ -33,7 +29,6 @@ public class PlayerActivityGraphCreatorTest { } /** - * * @return */ public static List createRandomSessionDataList() { @@ -53,25 +48,7 @@ public class PlayerActivityGraphCreatorTest { * */ @Test - public void testGetCount() { - List test = new ArrayList<>(); - long exp = 5; - test.add(5000L); - test.add(5000L); - test.add(5000L); - test.add(5000L); - test.add(5000L); - test.add(0L); - test.add(3450L); - test.add(37560L); - long result = PlayerActivityGraphCreator.getCount(test, 5000L); - assertEquals(exp, result); - } - - /** - * - */ - @Test + @Ignore("Outdated") public void testFilterSessions() { List test = new ArrayList<>(); SessionData invalid = new SessionData(0); @@ -86,49 +63,18 @@ public class PlayerActivityGraphCreatorTest { test.add(valid3); SessionData invalid2 = new SessionData(5000L, 5500L); test.add(invalid2); - List> result = PlayerActivityGraphCreator.filterAndTransformSessions(test, nowMinusScale); - List starts = result.get(0); - List ends = result.get(1); - assertTrue("Contained invalid session" + starts, !starts.contains(invalid.getSessionStart())); - assertTrue("Contained invalid session" + starts, !starts.contains(invalid2.getSessionStart())); - assertTrue("Contained invalid session" + ends, !ends.contains(invalid2.getSessionEnd())); - assertTrue("Contained invalid session" + ends, !ends.contains(invalid2.getSessionEnd())); - assertTrue("Did not contain valid session" + starts, starts.contains(valid1.getSessionStart())); - assertTrue("Did not contain valid session" + ends, ends.contains(valid1.getSessionEnd())); - assertTrue("Did not contain valid session" + starts, starts.contains(valid2.getSessionStart())); - assertTrue("Did not contain valid session" + ends, ends.contains(valid2.getSessionEnd())); - assertTrue("Did not contain valid session" + starts, starts.contains(valid3.getSessionStart())); - assertTrue("Did not contain valid session" + ends, ends.contains(valid3.getSessionEnd())); - } - - /** - * - */ - @Test - public void testGetSecond() { - Date test = new Date(); - long exp = test.toInstant().getEpochSecond() * 1000L; - long result = PlayerActivityGraphCreator.getSecond(test.getTime()); - assertEquals(exp, result); - } - - /** - * - */ - @Test - public void testGetSecond2() { - long exp = 2000L; - long result = PlayerActivityGraphCreator.getSecond(2456L); - assertEquals(exp, result); - } - - /** - * - */ - @Test - public void testGetSecond3() { - long exp = 2000L; - long result = PlayerActivityGraphCreator.getSecond(2956L); - assertEquals(exp, result); +// List> result = PlayerActivityGraphCreator.filterAndTransformSessions(test, nowMinusScale); +// List starts = result.get(0); +// List ends = result.get(1); +// assertTrue("Contained invalid session" + starts, !starts.contains(invalid.getSessionStart())); +// assertTrue("Contained invalid session" + starts, !starts.contains(invalid2.getSessionStart())); +// assertTrue("Contained invalid session" + ends, !ends.contains(invalid2.getSessionEnd())); +// assertTrue("Contained invalid session" + ends, !ends.contains(invalid2.getSessionEnd())); +// assertTrue("Did not contain valid session" + starts, starts.contains(valid1.getSessionStart())); +// assertTrue("Did not contain valid session" + ends, ends.contains(valid1.getSessionEnd())); +// assertTrue("Did not contain valid session" + starts, starts.contains(valid2.getSessionStart())); +// assertTrue("Did not contain valid session" + ends, ends.contains(valid2.getSessionEnd())); +// assertTrue("Did not contain valid session" + starts, starts.contains(valid3.getSessionStart())); +// assertTrue("Did not contain valid session" + ends, ends.contains(valid3.getSessionEnd())); } } From 89ee1a7bc73bfd0c1921f5d1867d8231d0a66dcb Mon Sep 17 00:00:00 2001 From: Rsl1122 Date: Tue, 25 Jul 2017 18:28:16 +0300 Subject: [PATCH 2/2] Fix Scatter & Length distribution graphs containing duplicate sessions --- .../djrapitops/plan/data/analysis/JoinInfoPart.java | 10 ++++------ Plan/src/main/resources/analysis.html | 2 -- Plan/src/main/resources/player.html | 2 -- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/Plan/src/main/java/com/djrapitops/plan/data/analysis/JoinInfoPart.java b/Plan/src/main/java/com/djrapitops/plan/data/analysis/JoinInfoPart.java index 940ccc98a..263065eed 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/analysis/JoinInfoPart.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/analysis/JoinInfoPart.java @@ -2,15 +2,13 @@ package main.java.com.djrapitops.plan.data.analysis; import com.djrapitops.plugin.api.TimeAmount; import com.djrapitops.plugin.utilities.Verify; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; import main.java.com.djrapitops.plan.data.SessionData; import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.analysis.AnalysisUtils; +import java.util.*; +import java.util.stream.Collectors; + /** * Part responsible for all Player login related analysis. * @@ -109,6 +107,6 @@ public class JoinInfoPart extends RawData { public void addSessions(UUID uuid, List sessions) { Verify.nullCheck(uuid); Verify.nullCheck(sessions); - this.sessions.put(uuid, sessions); + this.sessions.put(uuid, sessions.stream().distinct().collect(Collectors.toList())); } } diff --git a/Plan/src/main/resources/analysis.html b/Plan/src/main/resources/analysis.html index b39df7310..a623bbfaa 100644 --- a/Plan/src/main/resources/analysis.html +++ b/Plan/src/main/resources/analysis.html @@ -661,8 +661,6 @@ -

If the graph contains more sessions than login times, likely cause is use of /reload - (Restarts sessions).

diff --git a/Plan/src/main/resources/player.html b/Plan/src/main/resources/player.html index 3abb3da12..0e4edc5c7 100644 --- a/Plan/src/main/resources/player.html +++ b/Plan/src/main/resources/player.html @@ -549,8 +549,6 @@ -

If the graph contains more sessions than login times, likely cause is use of /reload - (Restarts sessions).