private JLabel arbitrageResult = null;
private int unknownPCTBcommods = 0;
private long startTime = 0;
+ private ProgressMonitor progmon = null;
private final static String PCTB_LIVE_HOST_URL = "http://pctb.crabdance.com/";
private final static String PCTB_TEST_HOST_URL = "http://pctb.ilk.org/";
private HashMap<String,Integer> commodMap;
public PrintStream dtxt = null;
- private PropertyChangeListener changeListener = new PropertyChangeListener() {
- public void propertyChange(PropertyChangeEvent e) {
- if(e.getNewValue() != null &&
- e.getPropertyName().equals
- (AccessibleContext.ACCESSIBLE_CHILD_PROPERTY)) {
- Accessible islandInfo =
- descendNodes(window,new int[] {0,1,0,0,2,2,0,0,0,0,1,2});;
- String text =
- islandInfo.getAccessibleContext().getAccessibleText()
- .getAtIndex(AccessibleText.SENTENCE,0);
- int index = text.indexOf(":");
- String name = text.substring(0,index);
- islandName = name;
- // if (dtxt!=null) dtxt.println(islandName);
- sidePanel.removePropertyChangeListener(this);
- latch.countDown();
- }
- }
- };
-
/*
* UTILITY METHODS AND SUBCLASSES
*
}
}
- private void progressNote(ProgressMonitor pm, String s) {
- String arb = null;
- new UI() { public void body() {
- if (arbitrageResult != null)
- arb = arbitrageResult.getText();
+ private void progressNote(final String s_in) throws Exception {
+ new UIX() { public void body() {
+ String arb = null;
+ arb = arbitrageResult.getText();
+ String s = s_in;
if (arb != null && arb.length() != 0)
s = "<html>" + arb + "<br>" + s;
- pm.setNote(s);
+ progmon.setNote(s);
}}.exec();
}
* a Window named "Puzzle Pirates" though.
*/
private void createGUI() {
- // on event thread
+ on_ui_thread();
frame = new JFrame("Jarrg Uploader");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
GridLayout layout = new GridLayout(2,1);
findMarket = new JButton("Upload Market Data");
findMarket.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
+ on_ui_thread();
findMarket.setEnabled(false);
resultSummary.setText("");
arbitrageResult.setText("");
error(e.toString());
e.printStackTrace();
}
- EventQueue.invokeAndWait(new Runnable() { public void run() {
- if(sidePanel != null) {
- sidePanel.removePropertyChangeListener(changeListener);
- }
- findMarket.setEnabled(true);
- }});
+ try {
+ new UIX() { public void body() {
+ if(sidePanel != null) {
+ sidePanel.removePropertyChangeListener(changeListener);
+ }
+ if (progmon != null) {
+ progmon.close();
+ progmon = null;
+ }
+ findMarket.setEnabled(true);
+ }}.exec();
+ } catch (Exception e) {
+ System.err.println("exception tidying on UI thread:");
+ e.printStackTrace();
+ }
}
}.start();
}
* error and error_html may be called from any thread
*/
- private Class UI implements Runnable {
- public virtual void body();
- public void run() { body(); };
- public void exec() {
+ private abstract class UIXR<ReturnType> implements Runnable {
+ public abstract ReturnType bodyr();
+ public ReturnType return_value;
+ public void run() { return_value = bodyr(); };
+ public ReturnType exec() throws Exception {
if (EventQueue.isDispatchThread()) {
- r.run();
+ this.run();
} else {
- invokeAndWait(r);
+ EventQueue.invokeAndWait(this);
}
+ return return_value;
};
};
+ private abstract class UIX extends UIXR<Object> implements Runnable {
+ public abstract void body();
+ public Object bodyr() { body(); return null; }
+ };
- private void error(String msg) {
- new UI() { public booolean body() {
- resultSummary.setText("failed");
- JOptionPane.showMessageDialog(frame,msg,"Error",
- JOptionPane.ERROR_MESSAGE);
- return true;
- }}.exec();
+ private void on_ui_thread() { assert(EventQueue.isDispatchThread()); }
+ private void on_our_thread() { assert(!EventQueue.isDispatchThread()); }
+
+ private void error(final String msg) {
+ try {
+ new UIX() { public void body() {
+ resultSummary.setText("failed");
+ JOptionPane.showMessageDialog(frame,msg,"Error",
+ JOptionPane.ERROR_MESSAGE);
+ }}.exec();
+ } catch (Exception e) {
+ System.err.println("exception reporting to UI thread:");
+ e.printStackTrace();
+ }
}
- private void error_html(String msg, String html) {
+ private void error_html(final String msg, String html) {
Pattern body = Pattern.compile("<body>(.*)</body>",
Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
Matcher m = body.matcher(html);
error(whole_msg);
}
+
+ private void setProgress(final int nv) throws Exception {
+ new UIX() { public void body() {
+ progmon.setProgress(nv);
+ }}.exec();
+ }
+ private boolean isCanceled() throws Exception {
+ return new UIXR<Boolean>() { public Boolean bodyr() {
+ return new Boolean(progmon.isCanceled());
+ }}.exec().booleanValue();
+ }
/*
* GUI MANIPULATION CALLBACKS
private PropertyChangeListener changeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
+ on_ui_thread();
if(e.getNewValue() != null &&
e.getPropertyName().equals
(AccessibleContext.ACCESSIBLE_CHILD_PROPERTY)) {
};
private void getIsland() {
- // runs on event thread
+ on_ui_thread();
// If the league tracker is there, we can skip the faff
// and ask for its tooltip, since we're on a boat
* oceanName variable
*/
private void getOcean() {
- // runs on event thread
+ on_ui_thread();
oceanName = null;
AccessibleContext topwindow = window.getAccessibleContext();
oceanName = topwindow.getAccessibleName()
};
private void runUpload() throws Exception {
+ on_our_thread();
+
boolean doneyarrg = false, donepctb = false;
YarrgTimestampFetcher yarrgts_thread = null;
yarrgts_thread.start();
}
- AccessibleTable accesstable = null;
- new UI() { public boolean body() {
- ProgressMonitor pm = new ProgressMonitor
+ final AccessibleTable accesstable =
+ new UIXR<AccessibleTable>() { public AccessibleTable bodyr() {
+ progmon = new ProgressMonitor
(frame,"Processing Market Data","Getting table data",0,100);
- pm.setMillisToDecideToPopup(0);
- pm.setMillisToPopup(0);
+ progmon.setMillisToDecideToPopup(0);
+ progmon.setMillisToPopup(0);
- accesstable = findMarketTable();
- if(accesstable == null) {
+ AccessibleTable at = findMarketTable();
+ if(at == null) {
error("Market table not found!"+
" Please open the Buy/Sell Commodities interface.");
- return;
+ return null;
}
- if(accesstable.getAccessibleRowCount() == 0) {
+ if(at.getAccessibleRowCount() == 0) {
error("No data found, please wait for the table to have data first!");
- return;
+ return null;
}
if(!isDisplayAll()) {
error("Please select \"All\" from the Display: popup menu.");
- return;
+ return null;
}
progresslog("(async) getisland...");
progresslog("getocean...");
getOcean();
progresslog("getocean done");
+
+ return at;
}}.exec();
if (accesstable == null) return;
progresslog("table check...");
- ArrayList<ArrayList<String>> data = null;
- String headings_expected[] = new String[]
- { "Commodity", "Trading outlet", "Buy price",
- "Will buy", "Sell price", "Will sell" };
+ final ArrayList<ArrayList<String>> data =
+ new UIXR<ArrayList<ArrayList<String>>>
+ () { public ArrayList<ArrayList<String>> bodyr() {
+ String headings_expected[] = new String[]
+ { "Commodity", "Trading outlet", "Buy price",
+ "Will buy", "Sell price", "Will sell" };
- new UI() { public void body() {
ArrayList<ArrayList<String>> headers =
getData(accesstable.getAccessibleColumnHeader());
if (headers.size() != 1) {
error("Table headings not one row! " + headers.toString());
- return;
+ return null;
}
if (headers.get(0).size() < 6 ||
headers.get(0).size() > 7) {
error("Table headings not six or seven columns! " + headers.toString());
- return;
+ return null;
}
for (int col=0; col<headings_expected.length; col++) {
String expd = headings_expected[col];
error("Table heading for column "+col
+" is not \""+expd+"\" but \""+got+"\".\n\n"
+"Please do not reorder the table when using this tool.");
- return;
+ return null;
}
}
progresslog("table read...");
- ArrayList<ArrayList<String>> data = getData(accesstable);
+ return getData(accesstable);
}}.exec();
- if (!data) return;
+ if (data == null) return;
if (showArbitrage) {
progresslog("arbitrage...");
if (uploadToYarrg && yarrgts != null) {
progresslog("yarrg prepare...");
- progressNote(pm, "Yarrg: Preparing data");
- pm.setProgress(10);
+ progressNote("Yarrg: Preparing data");
+ setProgress(10);
StringBuilder yarrgsb = new StringBuilder();
String yarrgdata; // string containing what we'll feed to yarrg
yarrgdata = yarrgsb.toString();
- progressNote(pm, "Yarrg: Uploading");
+ progressNote("Yarrg: Uploading");
progresslog("yarrg upload...");
doneyarrg = runYarrg(yarrgts, oceanName, islandName, yarrgdata);
if (uploadToPCTB) {
progresslog("pctb prepare...");
- progressNote(pm, "PCTB: Getting stall names");
- pm.setProgress(20);
- if(pm.isCanceled()) {
+ progressNote("PCTB: Getting stall names");
+ setProgress(20);
+ if(isCanceled()) {
return;
}
TreeSet<Offer> buys = new TreeSet<Offer>();
TreeSet<Offer> sells = new TreeSet<Offer>();
LinkedHashMap<String,Integer> stallMap = getStallMap(data);
- pm.setProgress(40);
- progressNote(pm, "PCTB: Sorting offers");
- if(pm.isCanceled()) {
+ setProgress(40);
+ progressNote("PCTB: Sorting offers");
+ if(isCanceled()) {
return;
}
// get commod map
// if (dtxt!=null) dtxt.println("\n\n\n"+buys);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
- pm.setProgress(60);
- progressNote(pm, "PCTB: Sending data");
- if(pm.isCanceled()) {
+ setProgress(60);
+ progressNote("PCTB: Sending data");
+ if(isCanceled()) {
return;
}
GZIPOutputStream out = new GZIPOutputStream(outStream);
InputStream in = sendInitialData(new ByteArrayInputStream(ba));
progresslog("pctb sent.");
if (in == null) return;
- pm.setProgress(80);
- if(pm.isCanceled()) {
+ setProgress(80);
+ if(isCanceled()) {
return;
}
- progressNote(pm, "PCTB: Waiting ...");
+ progressNote("PCTB: Waiting ...");
progresslog("pctb finish...");
donepctb = finishUpload(in);
progresslog("pctb done.");
}
- pm.setProgress(100);
+ setProgress(99);
+ String summary;
if ((uploadToPCTB && !donepctb) ||
(uploadToYarrg && !doneyarrg)) {
- resultSummary.setText("trouble");
+ summary= "trouble";
} else if (unknownPCTBcommods != 0) {
- resultSummary.setText("PCTB lacks "+unknownPCTBcommods+" commod");
+ summary= "PCTB lacks "+unknownPCTBcommods+" commod(s)";
} else if (donepctb || doneyarrg) {
- resultSummary.setText("Done " + islandName);
+ summary= "Done " + islandName;
} else {
- resultSummary.setText("uploaded nowhere!");
+ summary= "uploaded nowhere!";
}
+ final String summary_final = summary;
+ new UIX() { public void body() {
+ resultSummary.setText(summary_final);
+ }}.exec();
+
progresslog("done.");
}
* @return an array of record arrays, each representing a row of the table
*/
private ArrayList<ArrayList<String>> getData(AccessibleTable table) {
+ on_ui_thread();
ArrayList<ArrayList<String>> data = new ArrayList<ArrayList<String>>();
for (int i = 0; i < table.getAccessibleRowCount(); i++) {
ArrayList<String> row = new ArrayList<String>();
* otherwise <code>null</code>
*/
public AccessibleTable findMarketTable() {
+ on_ui_thread();
Accessible node1 = window;
Accessible node = descendNodes(node1,new int[] {0,1,0,0,0,0,1,0,0,1,0,0});
// commod market
* invalid.
*/
private Accessible descendNodes(Accessible parent, int[] path) {
+ on_ui_thread();
for(int i=0;i<path.length;i++) {
if (null == (parent = descend(parent, path[i]))) return null;
}
* or <code>null</code> if the child is not found.
*/
private Accessible descend(Accessible parent, int childNum) {
+ on_ui_thread();
if (parent == null) return null;
int children = parent.getAccessibleContext().getAccessibleChildrenCount();
if (childNum >= children) {
* @return the child or <code>null</code> if the child is not found.
*/
private Accessible descendByClass(Accessible parent, String classname) {
+ on_ui_thread();
if (parent == null) return null;
AccessibleContext ac = parent.getAccessibleContext();
int children = ac.getAccessibleChildrenCount();
* otherwise <code>false</code>
*/
private boolean isDisplayAll() {
+ on_ui_thread();
Accessible button = descendNodes(window,new int[] {0,1,0,0,0,0,1,0,0,0,1});
if(!(button instanceof JButton)) {
button = descendNodes(window,new int[] {0,1,0,0,0,0,1,0,1,0,0,0,1});
* the commodity id.
*/
private HashMap<String,Integer> getCommodMap() {
+ on_our_thread();
if(commodMap != null) {
return commodMap;
}
* @param file an InputStream open to the gzipped data we want to send
*/
private InputStream sendInitialData(InputStream file) throws IOException {
+ on_our_thread();
ClientHttpRequest http =
new ClientHttpRequest(PCTB_HOST_URL + "upload.php");
http.setParameter("marketdata","marketdata.gz",file,"application/gzip");
* @param in stream of data from the server to read
*/
private boolean finishUpload(InputStream in) throws IOException {
+ on_our_thread();
+
String html = readstreamstring(in);
debug_write_stringdata("pctb-initial.html", html);
Matcher m;
private InputStream post_for_yarrg(ClientHttpRequest http)
throws IOException {
+ on_our_thread();
if (!http.post()) {
String err = readstreamstring(http.resultstream());
error("<html><h1>Error reported by YARRG server</h1>\n" + err);
}
private @SuppressWarnings("unchecked")
- void calculateArbitrage(ArrayList<ArrayList<String>> data) {
+ void calculateArbitrage(ArrayList<ArrayList<String>> data)
+ throws InterruptedException {
int arbitrage = 0;
ArrayList<SortedSet<int[]>> arb_bs = null;
String lastcommod = null;
}
}
arbitrage += calculateArbitrageCommodity(arb_bs);
+ String arb;
if (arbitrage != 0) {
- arbitrageResult.setText("<html><strong>arbitrage: "+arbitrage
- +" poe</strong>");
+ arb = "<html><strong>arbitrage: "+arbitrage+" poe</strong>";
} else {
- arbitrageResult.setText("no arbitrage");
+ arb = "no arbitrage";
}
+ final String arb_final = arb;
+ EventQueue.invokeLater(new Runnable() { public void run() {
+ arbitrageResult.setText(arb_final);
+ }});
}
}