Skip to content

Commit 944537b

Browse files
committed
better handle api tasks
put all api calls into their own class. when each tracker is created, it will automatically call the api refreshes so they load in the background
1 parent 64a50ad commit 944537b

File tree

6 files changed

+196
-171
lines changed

6 files changed

+196
-171
lines changed

src/main/java/lol/hyper/customlauncher/Main.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -164,14 +164,8 @@ public static void main(String[] args) throws IOException, InterruptedException
164164

165165
// start reading invasions in the background
166166
InvasionTracker invasionTracker = new InvasionTracker();
167-
Thread t1 = new Thread(invasionTracker::startInvasionRefresh);
168167

169168
FieldOfficeTracker fieldOfficeTracker = new FieldOfficeTracker();
170-
fieldOfficeTracker.startFieldOfficeRefresh();
171-
Thread t2 = new Thread(fieldOfficeTracker::startFieldOfficeRefresh);
172-
173-
t1.start();
174-
t2.start();
175169

176170
// run the main window
177171
JFrame mainWindow = new MainWindow(invasionTracker, fieldOfficeTracker);

src/main/java/lol/hyper/customlauncher/accounts/windows/MainWindow.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ public MainWindow(InvasionTracker invasionTracker, FieldOfficeTracker fieldOffic
9595
JButton invasionsButton = new JButton("Invasions");
9696
invasionsButton.addActionListener(
9797
e -> {
98-
invasionTracker.showWindow();
98+
Thread t1 = new Thread(invasionTracker::showWindow);
99+
t1.start();
99100
});
100101
invasionsButton.setAlignmentX(Component.CENTER_ALIGNMENT);
101102
invasionsButton.setMaximumSize(new Dimension(300, invasionsButton.getMinimumSize().height));
@@ -105,7 +106,8 @@ public MainWindow(InvasionTracker invasionTracker, FieldOfficeTracker fieldOffic
105106
JButton fieldOfficesButton = new JButton("Field Offices");
106107
fieldOfficesButton.addActionListener(
107108
e -> {
108-
fieldOfficeTracker.showWindow();
109+
Thread t1 = new Thread(fieldOfficeTracker::showWindow);
110+
t1.start();
109111
});
110112
fieldOfficesButton.setAlignmentX(Component.CENTER_ALIGNMENT);
111113
fieldOfficesButton.setMaximumSize(
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package lol.hyper.customlauncher.fieldofficetracker;
2+
3+
import lol.hyper.customlauncher.accounts.JSONManager;
4+
import lol.hyper.customlauncher.generic.ErrorWindow;
5+
import org.json.JSONObject;
6+
7+
import java.awt.event.ActionEvent;
8+
import java.awt.event.ActionListener;
9+
import java.util.Iterator;
10+
import java.util.Map;
11+
12+
public class FieldOfficeTask implements ActionListener {
13+
14+
final String FIELD_OFFICE_URL = "https://www.toontownrewritten.com/api/fieldoffices";
15+
16+
private final FieldOfficeTracker fieldOfficeTracker;
17+
18+
public FieldOfficeTask(FieldOfficeTracker fieldOfficeTracker) {
19+
this.fieldOfficeTracker = fieldOfficeTracker;
20+
}
21+
22+
@Override
23+
public void actionPerformed(ActionEvent e) {
24+
// grab the field offices object in the request
25+
// each field office is stored under the JSONObject "fieldOffices"
26+
JSONObject fieldOfficeRoot = JSONManager.requestJSON(FIELD_OFFICE_URL);
27+
if (fieldOfficeRoot == null) {
28+
ErrorWindow errorWindow = new ErrorWindow("Unable to read field office API!", null);
29+
errorWindow.dispose();
30+
return;
31+
}
32+
JSONObject fieldOfficeJSON = fieldOfficeRoot.getJSONObject("fieldOffices");
33+
34+
fieldOfficeTracker.logger.info("Reading " + FIELD_OFFICE_URL + " for current field offices...");
35+
36+
// go through all the field offices from the API
37+
Iterator<String> keys = fieldOfficeJSON.keys();
38+
while (keys.hasNext()) {
39+
String key = keys.next();
40+
// each field office json is named the zone ID
41+
JSONObject zoneJSON = fieldOfficeJSON.getJSONObject(key);
42+
// update field office data
43+
if (fieldOfficeTracker.fieldOffices.containsKey(Integer.valueOf(key))) {
44+
FieldOffice office = fieldOfficeTracker.fieldOffices.get(Integer.parseInt(key));
45+
office.setOpen(zoneJSON.getBoolean("open"));
46+
office.setTotalAnnexes(zoneJSON.getInt("annexes"));
47+
} else {
48+
// new field office
49+
int difficulty = zoneJSON.getInt("difficulty") + 1; // they zero index this
50+
int totalAnnexes = zoneJSON.getInt("annexes");
51+
boolean open = zoneJSON.getBoolean("open");
52+
FieldOffice office =
53+
new FieldOffice(Integer.parseInt(key), difficulty, open, totalAnnexes);
54+
// add it to our master list
55+
fieldOfficeTracker.fieldOffices.put(Integer.parseInt(key), office);
56+
fieldOfficeTracker.showNotification(office, true);
57+
}
58+
}
59+
60+
// we look at the current field office list and see if any of them
61+
// are not on the field office JSON (aka that field office is gone)
62+
Iterator<Map.Entry<Integer, FieldOffice>> it = fieldOfficeTracker.fieldOffices.entrySet().iterator();
63+
while (it.hasNext()) {
64+
Map.Entry<Integer, FieldOffice> pair = it.next();
65+
String key = String.valueOf(pair.getKey());
66+
if (!fieldOfficeJSON.has(key)) {
67+
fieldOfficeTracker.showNotification(pair.getValue(), false);
68+
it.remove();
69+
}
70+
}
71+
72+
fieldOfficeTracker.calls++;
73+
}
74+
}

src/main/java/lol/hyper/customlauncher/fieldofficetracker/FieldOfficeTracker.java

Lines changed: 13 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,25 @@
33
import dorkbox.notify.Notify;
44
import dorkbox.notify.Pos;
55
import lol.hyper.customlauncher.Main;
6-
import lol.hyper.customlauncher.accounts.JSONManager;
7-
import lol.hyper.customlauncher.generic.ErrorWindow;
86
import org.apache.logging.log4j.LogManager;
97
import org.apache.logging.log4j.Logger;
10-
import org.json.JSONObject;
118

129
import javax.swing.*;
1310
import javax.swing.Timer;
1411
import javax.swing.table.DefaultTableModel;
1512
import java.awt.*;
13+
import java.awt.event.ActionListener;
1614
import java.util.*;
1715
import java.util.List;
18-
import java.util.concurrent.Executors;
19-
import java.util.concurrent.ScheduledExecutorService;
20-
import java.util.concurrent.TimeUnit;
2116

2217
public class FieldOfficeTracker {
2318

2419
public final HashMap<Integer, FieldOffice> fieldOffices = new HashMap<>();
2520
public final Logger logger = LogManager.getLogger(FieldOfficeTracker.class);
26-
public ScheduledExecutorService schedulerAPI;
2721
public JTable fieldOfficeTable;
2822
public DefaultTableModel fieldOfficeTableModel;
2923
public JFrame frame;
3024
public static final HashMap<Integer, String> zonesToStreets = new HashMap<>();
31-
public Timer timer;
3225
int calls = 0;
3326

3427
public FieldOfficeTracker() {
@@ -44,6 +37,7 @@ public FieldOfficeTracker() {
4437
zonesToStreets.put(5300, "Oak Street");
4538
zonesToStreets.put(9100, "Lullaby Lane");
4639
zonesToStreets.put(9200, "Pajama Place");
40+
startFieldOfficeRefresh();
4741
}
4842

4943
/** Open the field office window. */
@@ -79,14 +73,11 @@ public void showWindow() {
7973
scrollPane.setVisible(true);
8074
panel.add(scrollPane);
8175

82-
// start the table update scheduler
83-
timer = new Timer(1000, e -> updateFieldOfficeList());
84-
timer.setRepeats(true);
85-
timer.setInitialDelay(0);
76+
ActionListener actionListener = e -> updateFieldOfficeList();
77+
Timer timer = new Timer(0, actionListener);
78+
timer.setDelay(500);
8679
timer.start();
8780

88-
startFieldOfficeRefresh();
89-
9081
frame.pack();
9182
frame.setSize(500, 400);
9283
frame.add(panel);
@@ -133,76 +124,23 @@ private void updateFieldOfficeList() {
133124
}
134125

135126
/** Read field office API every 5 seconds. */
136-
public void startFieldOfficeRefresh() {
137-
schedulerAPI = Executors.newScheduledThreadPool(0);
138-
schedulerAPI.scheduleAtFixedRate(this::readFieldOfficeAPI, 0, 10, TimeUnit.SECONDS);
139-
}
140-
141-
/** Read the TTR API and get the current field offices. */
142-
private void readFieldOfficeAPI() {
143-
String FIELD_OFFICE_URL = "https://www.toontownrewritten.com/api/fieldoffices";
144-
145-
// grab the field offices object in the request
146-
// each field office is stored under the JSONObject "fieldOffices"
147-
JSONObject fieldOfficeRoot = JSONManager.requestJSON(FIELD_OFFICE_URL);
148-
if (fieldOfficeRoot == null) {
149-
ErrorWindow errorWindow = new ErrorWindow("Unable to read field office API!", null);
150-
errorWindow.dispose();
151-
return;
152-
}
153-
JSONObject fieldOfficeJSON = fieldOfficeRoot.getJSONObject("fieldOffices");
154-
155-
logger.info("Reading " + FIELD_OFFICE_URL + " for current field offices...");
156-
157-
// go through all the field offices from the API
158-
Iterator<String> keys = fieldOfficeJSON.keys();
159-
while (keys.hasNext()) {
160-
String key = keys.next();
161-
// each field office json is named the zone ID
162-
JSONObject zoneJSON = fieldOfficeJSON.getJSONObject(key);
163-
// update field office data
164-
if (fieldOffices.containsKey(Integer.valueOf(key))) {
165-
FieldOffice office = fieldOffices.get(Integer.parseInt(key));
166-
office.setOpen(zoneJSON.getBoolean("open"));
167-
office.setTotalAnnexes(zoneJSON.getInt("annexes"));
168-
} else {
169-
// new field office
170-
int difficulty = zoneJSON.getInt("difficulty") + 1; // they zero index this
171-
int totalAnnexes = zoneJSON.getInt("annexes");
172-
boolean open = zoneJSON.getBoolean("open");
173-
FieldOffice office =
174-
new FieldOffice(Integer.parseInt(key), difficulty, open, totalAnnexes);
175-
// add it to our master list
176-
fieldOffices.put(Integer.parseInt(key), office);
177-
showNotification(office, true);
178-
}
179-
}
180-
181-
// we look at the current field office list and see if any of them
182-
// are not on the field office JSON (aka that field office is gone)
183-
Iterator<Map.Entry<Integer, FieldOffice>> it = fieldOffices.entrySet().iterator();
184-
while (it.hasNext()) {
185-
Map.Entry<Integer, FieldOffice> pair = it.next();
186-
String key = String.valueOf(pair.getKey());
187-
if (!fieldOfficeJSON.has(key)) {
188-
showNotification(pair.getValue(), false);
189-
it.remove();
190-
}
191-
}
192-
193-
calls++;
127+
private void startFieldOfficeRefresh() {
128+
ActionListener actionListener = new FieldOfficeTask(this);
129+
Timer timer = new Timer(0, actionListener);
130+
timer.setDelay(5000);
131+
timer.start();
194132
}
195133

196-
private void showNotification(FieldOffice fieldOffice, boolean newFieldOffice) {
134+
public void showNotification(FieldOffice fieldOffice, boolean newFieldOffice) {
197135
// don't spam the user with a bunch of notifications at once when we first launch
198136
if (calls == 0) {
199137
return;
200138
}
201139
Notify notify;
202140
if (newFieldOffice) {
203-
notify = Notify.create().title("New Field Office!").text(zonesToStreets.get(fieldOffice.getArea()) + " - " + fieldOffice.getDifficulty() + " star").darkStyle().position(Pos.BOTTOM_RIGHT).hideAfter(5000);
141+
notify = Notify.create().title("New Field Office!").text(zonesToStreets.get(fieldOffice.getArea()) + " - " + fieldOffice.getDifficulty() + " star").darkStyle().position(Pos.BOTTOM_RIGHT).hideAfter(5000).image(Main.icon);
204142
} else {
205-
notify = Notify.create().title("Field Office Gone!").text(zonesToStreets.get(fieldOffice.getArea()) + " - " + fieldOffice.getDifficulty() + " star").darkStyle().position(Pos.BOTTOM_RIGHT).hideAfter(5000);
143+
notify = Notify.create().title("Field Office Gone!").text(zonesToStreets.get(fieldOffice.getArea()) + " - " + fieldOffice.getDifficulty() + " star").darkStyle().position(Pos.BOTTOM_RIGHT).hideAfter(5000).image(Main.icon);
206144
}
207145
notify.showInformation();
208146
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package lol.hyper.customlauncher.invasiontracker;
2+
3+
import lol.hyper.customlauncher.accounts.JSONManager;
4+
import lol.hyper.customlauncher.generic.ErrorWindow;
5+
import org.json.JSONObject;
6+
7+
import java.awt.event.ActionEvent;
8+
import java.awt.event.ActionListener;
9+
import java.time.Instant;
10+
import java.time.ZoneId;
11+
import java.util.Iterator;
12+
import java.util.Map;
13+
14+
public class InvasionTask implements ActionListener {
15+
16+
final String INVASION_URL = "https://api.toon.plus/invasions/";
17+
18+
private final InvasionTracker invasionTracker;
19+
20+
public InvasionTask(InvasionTracker invasionTracker) {
21+
this.invasionTracker = invasionTracker;
22+
}
23+
24+
@Override
25+
public void actionPerformed(ActionEvent e) {
26+
// grab the invasions object in the request
27+
// that hold all the invasions
28+
JSONObject invasionsJSON = JSONManager.requestJSON(INVASION_URL);
29+
if (invasionsJSON == null) {
30+
ErrorWindow errorWindow = new ErrorWindow("Unable to read invasion API!", null);
31+
errorWindow.dispose();
32+
return;
33+
}
34+
35+
invasionTracker.logger.info("Reading " + INVASION_URL + " for current invasions...");
36+
37+
// iterate through each of the invasions (separate JSONs)
38+
Iterator<String> keys = invasionsJSON.keys();
39+
while (keys.hasNext()) {
40+
String key = keys.next();
41+
String district = key.substring(0, key.indexOf('/'));
42+
// if we do not have that invasion stored, create a new invasion object
43+
// and add it to the list
44+
if (!invasionTracker.invasions.containsKey(district)) {
45+
JSONObject temp = invasionsJSON.getJSONObject(key);
46+
String cogType = temp.getString("Type");
47+
int cogsDefeated = temp.getInt("CurrentProgress");
48+
int cogsTotal = temp.getInt("MaxProgress");
49+
boolean megaInvasion = temp.getBoolean("MegaInvasion");
50+
Invasion newInvasion =
51+
new Invasion(cogType, cogsDefeated, cogsTotal, district, megaInvasion);
52+
newInvasion.endTime =
53+
Instant.parse(temp.getString("EstimatedCompletion"))
54+
.atZone(ZoneId.systemDefault());
55+
invasionTracker.invasions.put(district, newInvasion);
56+
invasionTracker.showNotification(newInvasion, true);
57+
} else {
58+
if (!invasionTracker.invasions.containsKey(district)) {
59+
return; // JUST IN CASE
60+
}
61+
// if we already have it saved, update the information that we have saved already
62+
// we want to update the total cogs defeated and the end time
63+
Invasion tempInv = invasionTracker.invasions.get(district);
64+
JSONObject temp = invasionsJSON.getJSONObject(key);
65+
// ignore mega invasion cog count
66+
if (!temp.getBoolean("MegaInvasion")) {
67+
int cogsDefeated = temp.getInt("CurrentProgress");
68+
tempInv.updateCogsDefeated(cogsDefeated);
69+
tempInv.endTime =
70+
Instant.parse(temp.getString("EstimatedCompletion"))
71+
.atZone(ZoneId.systemDefault());
72+
}
73+
}
74+
}
75+
76+
// we look at the current invasion list and see if any invasions
77+
// are not on the invasion JSON (aka that invasion is gone)
78+
Iterator<Map.Entry<String, Invasion>> it = invasionTracker.invasions.entrySet().iterator();
79+
while (it.hasNext()) {
80+
Map.Entry<String, Invasion> pair = it.next();
81+
String key = pair.getKey() + "/" + pair.getValue().getCogType();
82+
if (!invasionsJSON.has(key)) {
83+
invasionTracker.showNotification(pair.getValue(), false);
84+
it.remove();
85+
}
86+
}
87+
88+
invasionTracker.calls++;
89+
}
90+
}

0 commit comments

Comments
 (0)