diff --git a/src/main/java/com/afkstatstracker/AfkStatsTrackerPanel.java b/src/main/java/com/afkstatstracker/AfkStatsTrackerPanel.java index ba8527c..2d33e77 100644 --- a/src/main/java/com/afkstatstracker/AfkStatsTrackerPanel.java +++ b/src/main/java/com/afkstatstracker/AfkStatsTrackerPanel.java @@ -1,5 +1,6 @@ package com.afkstatstracker; +import com.google.gson.Gson; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; @@ -26,8 +27,10 @@ import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JLabel; +import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.ImageIcon; @@ -42,6 +45,7 @@ public class AfkStatsTrackerPanel extends PluginPanel { private final AfkStatsTrackerPlugin plugin; private final SessionHistoryManager sessionHistoryManager; + private final Gson gson; private Timer timer; private JButton startButton; @@ -60,13 +64,14 @@ public class AfkStatsTrackerPanel extends PluginPanel private JScrollPane historyScrollPane; private boolean historyExpanded = true; - public AfkStatsTrackerPanel(AfkStatsTrackerPlugin plugin, SessionHistoryManager sessionHistoryManager) + public AfkStatsTrackerPanel(AfkStatsTrackerPlugin plugin, SessionHistoryManager sessionHistoryManager, Gson gson) { // wrap=false: we manage our own scroll so the buttons/stats stay pinned and only history data scrolls super(false); this.plugin = plugin; this.sessionHistoryManager = sessionHistoryManager; + this.gson = gson; setLayout(new BorderLayout()); @@ -290,24 +295,23 @@ public void mouseClicked(MouseEvent e) // Copy icon JLabel copyIcon = createHoverIcon( new ImageIcon(ImageUtil.loadImageResource(AfkStatsTrackerPanel.class, "copy.png")), - "Copy session stats"); + "Copy session"); copyIcon.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { - String lengthStr = DurationFormatter.format(session.getEndTime() - session.getStartTime()); - - String text = String.format( - "Session: %s\nLength: %s\nConsistency: %d\nAvg Interval: %.0fms\nAvg Distance: %.1f%%\nClicks: %d", - session.getName(), lengthStr, - session.getConsistencyScore(), - session.getAvgInterval(), - session.getAvgDistancePercent(), - session.getClickCount()); - - Toolkit.getDefaultToolkit().getSystemClipboard() - .setContents(new StringSelection(text), null); + JPopupMenu menu = new JPopupMenu(); + + JMenuItem copyStats = new JMenuItem("Copy stats"); + copyStats.addActionListener(a -> copyToClipboard(formatSessionText(session))); + menu.add(copyStats); + + JMenuItem copyJson = new JMenuItem("Copy JSON"); + copyJson.addActionListener(a -> copyToClipboard(gson.toJson(roundForExport(session)))); + menu.add(copyJson); + + menu.show(copyIcon, e.getX(), e.getY()); } }); @@ -395,6 +399,37 @@ protected void paintComponent(Graphics g) return icon; } + private String formatSessionText(Session session) + { + String lengthStr = DurationFormatter.format(session.getEndTime() - session.getStartTime()); + return String.format( + "Session: %s\nLength: %s\nConsistency: %d\nAvg Interval: %.0fms\nAvg Distance: %.1f%%\nClicks: %d", + session.getName(), lengthStr, + session.getConsistencyScore(), + session.getAvgInterval(), + session.getAvgDistancePercent(), + session.getClickCount()); + } + + private void copyToClipboard(String text) + { + Toolkit.getDefaultToolkit().getSystemClipboard() + .setContents(new StringSelection(text), null); + } + + static Session roundForExport(Session session) + { + return new Session( + session.getId(), + session.getName(), + session.getStartTime(), + session.getEndTime(), + session.getClickCount(), + session.getConsistencyScore(), + Math.round(session.getAvgInterval() * 100) / 100.0, + Math.round(session.getAvgDistancePercent() * 100) / 100.0); + } + private void makeEditable(JPanel row, Session session, JLabel nameLabel) { JTextField textField = new JTextField(session.getName()); diff --git a/src/main/java/com/afkstatstracker/AfkStatsTrackerPlugin.java b/src/main/java/com/afkstatstracker/AfkStatsTrackerPlugin.java index cd7bffc..e16304f 100644 --- a/src/main/java/com/afkstatstracker/AfkStatsTrackerPlugin.java +++ b/src/main/java/com/afkstatstracker/AfkStatsTrackerPlugin.java @@ -79,7 +79,7 @@ public void save(String json) log.info("AFK Stats Tracker plugin started!"); - panel = new AfkStatsTrackerPanel(this, sessionHistoryManager); + panel = new AfkStatsTrackerPanel(this, sessionHistoryManager, gson); // Add to toolbar navButton = NavigationButton.builder() diff --git a/src/test/java/com/afkstatstracker/SessionJsonTest.java b/src/test/java/com/afkstatstracker/SessionJsonTest.java new file mode 100644 index 0000000..57fc63d --- /dev/null +++ b/src/test/java/com/afkstatstracker/SessionJsonTest.java @@ -0,0 +1,42 @@ +package com.afkstatstracker; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class SessionJsonTest +{ + @Test + public void sessionSerializesWithWebsiteContractFieldNames() + { + Session session = new Session("id-1", "Test", 1000L, 61000L, 42, 87L, 1500.5, 12.3); + JsonObject json = new JsonParser().parse(new Gson().toJson(session)).getAsJsonObject(); + + assertTrue(json.has("name")); + assertTrue(json.has("startTime")); + assertTrue(json.has("endTime")); + assertTrue(json.has("clickCount")); + assertTrue(json.has("consistencyScore")); + assertTrue(json.has("avgInterval")); + assertTrue(json.has("avgDistancePercent")); + assertEquals(42, json.get("clickCount").getAsInt()); + assertEquals(87L, json.get("consistencyScore").getAsLong()); + assertEquals(1000L, json.get("startTime").getAsLong()); + } + + @Test + public void roundForExportRoundsFloatsToTwoDecimals() + { + Session session = new Session("id-1", "Test", 1000L, 61000L, 7, 68L, 521.1666666666666, 4.014945489298668); + Session rounded = AfkStatsTrackerPanel.roundForExport(session); + + assertEquals(521.17, rounded.getAvgInterval(), 0.0); + assertEquals(4.01, rounded.getAvgDistancePercent(), 0.0); + assertEquals(7, rounded.getClickCount()); + assertEquals(68L, rounded.getConsistencyScore()); + } +}