X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~yarrgweb/git?a=blobdiff_plain;f=src%2Fnet%2Fchiark%2Fyarrg%2FMarketUploader.java;h=4f50228a7b77f8131902fb5e19228500322f3725;hb=f0aff42beee7a04001ec97093704144074b35fc6;hp=5dc7e6cca0e7429d21c1bff0553510dc62fe6e5f;hpb=85a3df43ff414a1c12420eddf0ee372d9682aee8;p=jarrg-ian.git diff --git a/src/net/chiark/yarrg/MarketUploader.java b/src/net/chiark/yarrg/MarketUploader.java index 5dc7e6c..4f50228 100644 --- a/src/net/chiark/yarrg/MarketUploader.java +++ b/src/net/chiark/yarrg/MarketUploader.java @@ -43,6 +43,7 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { 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/"; @@ -71,26 +72,6 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { private HashMap 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 * @@ -105,7 +86,7 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { } } - private void progresslog(String s) { + private void debuglog(String s) { if (dtxt == null) return; long now = new Date().getTime(); dtxt.println("progress "+(now - startTime)+"ms "+s); @@ -265,14 +246,14 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { } } - 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 = "" + arb + "
" + s; - pm.setNote(s); + progmon.setNote(s); }}.exec(); } @@ -307,8 +288,7 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { uploadToPCTB=prefs.getBoolean("uploadToPCTB", true); showArbitrage=prefs.getBoolean("showArbitrage", true); - if (dtxt!=null) dtxt.println("main on dispatch thread: "+ - EventQueue.isDispatchThread()); + debuglog("main on dispatch thread: "+EventQueue.isDispatchThread()); EventQueue.invokeLater(this); } @@ -317,12 +297,12 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { * every top-level window, and if it */ public void run() { - if (dtxt!=null) dtxt.println("MarketUploader run()..."); + debuglog("MarketUploader run()..."); if (EventQueueMonitor.isGUIInitialized()) { - if (dtxt!=null) dtxt.println("MarketUploader GUI already ready"); + debuglog("MarketUploader GUI already ready"); guiInitialized(); } else { - if (dtxt!=null) dtxt.println("MarketUploader waiting for GUI"); + debuglog("MarketUploader waiting for GUI"); EventQueueMonitor.addGUIInitializedListener(this); } } @@ -331,13 +311,13 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { Window ws[]= EventQueueMonitor.getTopLevelWindows(); EventQueueMonitor.addTopLevelWindowListener(this); for (int i=0; i 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 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("(.*)", Pattern.DOTALL | Pattern.CASE_INSENSITIVE); Matcher m = body.matcher(html); @@ -450,10 +453,21 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { } String whole_msg = "

Error

"+msg +"

PCTB Server said:

"+html+"
"; - if (dtxt!=null) dtxt.println("###" + whole_msg + "###"); + debuglog("###" + whole_msg + "###"); 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() { public Boolean bodyr() { + return new Boolean(progmon.isCanceled()); + }}.exec().booleanValue(); + } /* * GUI MANIPULATION CALLBACKS @@ -461,6 +475,7 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { private PropertyChangeListener changeListener = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent e) { + on_ui_thread(); if(e.getNewValue() != null && e.getPropertyName().equals (AccessibleContext.ACCESSIBLE_CHILD_PROPERTY)) { @@ -471,7 +486,7 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { int index = text.indexOf(":"); String name = text.substring(0,index); islandName = name; - // if (dtxt!=null) dtxt.println(islandName); + // debuglog(islandName); sidePanel.removePropertyChangeListener(this); latch.countDown(); } @@ -479,7 +494,7 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { }; 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 @@ -531,7 +546,7 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { * oceanName variable */ private void getOcean() { - // runs on event thread + on_ui_thread(); oceanName = null; AccessibleContext topwindow = window.getAccessibleContext(); oceanName = topwindow.getAccessibleName() @@ -553,7 +568,7 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { public void run() { try { ts = getYarrgTimestamp(); - progresslog("(async) yarrg timestamp ready."); + debuglog("(async) yarrg timestamp ready."); } catch(Exception e) { error("Error getting YARRG timestamp: "+e); } @@ -561,57 +576,61 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { }; private void runUpload() throws Exception { + on_our_thread(); + boolean doneyarrg = false, donepctb = false; YarrgTimestampFetcher yarrgts_thread = null; - progresslog("starting"); + debuglog("starting"); if (uploadToYarrg) { - progresslog("(async) yarrg timestamp..."); + debuglog("(async) yarrg timestamp..."); yarrgts_thread = new YarrgTimestampFetcher(); yarrgts_thread.start(); } - AccessibleTable accesstable = null; - new UI() { public boolean body() { - ProgressMonitor pm = new ProgressMonitor + final AccessibleTable accesstable = + new UIXR() { 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..."); + debuglog("(async) getisland..."); getIsland(); - progresslog("getocean..."); + debuglog("getocean..."); getOcean(); - progresslog("getocean done"); + debuglog("getocean done"); + + return at; }}.exec(); if (accesstable == null) return; if (latch != null) { latch.await(2, java.util.concurrent.TimeUnit.SECONDS); } - progresslog("(async) getisland done"); + debuglog("(async) getisland done"); String yarrgts = null; if (yarrgts_thread != null) { - progresslog("(async) yarrg timestamp join..."); + debuglog("(async) yarrg timestamp join..."); yarrgts_thread.join(); - progresslog("(async) yarrg timestamp joined."); + debuglog("(async) yarrg timestamp joined."); yarrgts = yarrgts_thread.ts; } @@ -620,24 +639,25 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { return; } - progresslog("table check..."); + debuglog("table check..."); - ArrayList> data = null; - String headings_expected[] = new String[] - { "Commodity", "Trading outlet", "Buy price", - "Will buy", "Sell price", "Will sell" }; + final ArrayList> data = + new UIXR>> + () { public ArrayList> bodyr() { + String headings_expected[] = new String[] + { "Commodity", "Trading outlet", "Buy price", + "Will buy", "Sell price", "Will sell" }; - new UI() { public void body() { ArrayList> 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> data = getData(accesstable); + return getData(accesstable); }}.exec(); - if (!data) return; + if (data == null) return; if (showArbitrage) { - progresslog("arbitrage..."); + debuglog("arbitrage..."); calculateArbitrage(data); - progresslog("arbitrage done."); + debuglog("arbitrage done."); } if (uploadToYarrg && yarrgts != null) { - progresslog("yarrg prepare..."); - progressNote(pm, "Yarrg: Preparing data"); - pm.setProgress(10); + debuglog("yarrg prepare..."); + progressNote("Yarrg: Preparing data"); + setProgress(10); StringBuilder yarrgsb = new StringBuilder(); String yarrgdata; // string containing what we'll feed to yarrg @@ -684,44 +704,44 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { yarrgdata = yarrgsb.toString(); - progressNote(pm, "Yarrg: Uploading"); - progresslog("yarrg upload..."); + progressNote("Yarrg: Uploading"); + debuglog("yarrg upload..."); doneyarrg = runYarrg(yarrgts, oceanName, islandName, yarrgdata); - progresslog("yarrg done."); + debuglog("yarrg done."); } if (uploadToPCTB) { - progresslog("pctb prepare..."); - progressNote(pm, "PCTB: Getting stall names"); - pm.setProgress(20); - if(pm.isCanceled()) { + debuglog("pctb prepare..."); + progressNote("PCTB: Getting stall names"); + setProgress(20); + if(isCanceled()) { return; } TreeSet buys = new TreeSet(); TreeSet sells = new TreeSet(); LinkedHashMap 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 - progresslog("pctb commodmap..."); + debuglog("pctb commodmap..."); HashMap commodMap = getCommodMap(); if(commodMap == null) { return; } - progresslog("pctb commodmap done."); + debuglog("pctb commodmap done."); int[] offerCount = getBuySellMaps(data,buys,sells,stallMap,commodMap); - // if (dtxt!=null) dtxt.println(sells); - // if (dtxt!=null) dtxt.println("\n\n\n"+buys); + // debuglog(sells); + // debuglog("\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); @@ -731,36 +751,42 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { dos.writeBytes(getAbbrevStallList(stallMap)); writeBuySellOffers(buys,sells,offerCount,out); out.finish(); - progresslog("pctb send..."); + debuglog("pctb send..."); byte[] ba = outStream.toByteArray(); debug_write_bytes("pctb-marketdata.gz", ba); InputStream in = sendInitialData(new ByteArrayInputStream(ba)); - progresslog("pctb sent."); + debuglog("pctb sent."); if (in == null) return; - pm.setProgress(80); - if(pm.isCanceled()) { + setProgress(80); + if(isCanceled()) { return; } - progressNote(pm, "PCTB: Waiting ..."); - progresslog("pctb finish..."); + progressNote("PCTB: Waiting ..."); + debuglog("pctb finish..."); donepctb = finishUpload(in); - progresslog("pctb done."); + debuglog("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!"; } - progresslog("done."); + final String summary_final = summary; + new UIX() { public void body() { + resultSummary.setText(summary_final); + }}.exec(); + + debuglog("done."); } /** @@ -771,6 +797,7 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { * @return an array of record arrays, each representing a row of the table */ private ArrayList> getData(AccessibleTable table) { + on_ui_thread(); ArrayList> data = new ArrayList>(); for (int i = 0; i < table.getAccessibleRowCount(); i++) { ArrayList row = new ArrayList(); @@ -788,18 +815,19 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { * otherwise null */ 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 // commod market: {0,1,0,0,0,0,1,0,0,1,0} {0,1,0,0,0,0,1,0,1,0,0,1,0,0}) - // if (dtxt!=null) dtxt.println(node); + // debuglog(node); if (!(node instanceof JTable)) { node = descendNodes(node1,new int[] {0,1,0,0,0,0,1,0,1,0,0,1,0,0}); // commod market } if (!(node instanceof JTable)) return null; AccessibleTable table = node.getAccessibleContext().getAccessibleTable(); - // if (dtxt!=null) dtxt.println(table); + // debuglog(table); return table; } @@ -815,6 +843,7 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { * invalid. */ private Accessible descendNodes(Accessible parent, int[] path) { + on_ui_thread(); for(int i=0;inull 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) { - if (dtxt!=null) dtxt.println("DESCEND "+childNum+" > " - +children+" NOT FOUND"); + debuglog("DESCEND "+childNum+" > "+children+" NOT FOUND"); return null; } Accessible child = parent.getAccessibleContext() .getAccessibleChild(childNum); - if (dtxt!=null) dtxt.println("DESCEND "+childNum+" " - +child.getClass().getName()+" OK"); + debuglog("DESCEND "+childNum+" "+child.getClass().getName()+" OK"); return child; } @@ -853,17 +881,18 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { * @return the child or null 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(); for (int i=0; ifalse */ 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}); @@ -897,6 +927,7 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { * the commodity id. */ private HashMap getCommodMap() { + on_our_thread(); if(commodMap != null) { return commodMap; } @@ -996,8 +1027,7 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { } } catch(IllegalArgumentException e) { unknownPCTBcommods++; - if (dtxt!=null) dtxt.println("Error: Unsupported Commodity \"" - + offer.get(0) + "\""); + debuglog("Error: Unsupported Commodity \"" + offer.get(0) + "\""); } } if (buySellCount[0]==0 && buySellCount[1]==0) { @@ -1144,6 +1174,7 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { * @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"); @@ -1177,6 +1208,8 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { * @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; @@ -1238,6 +1271,7 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { private InputStream post_for_yarrg(ClientHttpRequest http) throws IOException { + on_our_thread(); if (!http.post()) { String err = readstreamstring(http.resultstream()); error("

Error reported by YARRG server

\n" + err); @@ -1291,7 +1325,7 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { } private int calculateArbitrageCommodity(ArrayList> arb_bs) { - // if (dtxt!=null) dtxt.println("ARBITRAGE?"); + // debuglog("ARBITRAGE?"); int profit = 0; SortedSet buys = arb_bs.get(0); SortedSet sells = arb_bs.get(1); @@ -1307,9 +1341,9 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { int unitprofit = buy[0] - sell[0]; int count = buy[1] < sell[1] ? buy[1] : sell[1]; - // if (dtxt!=null) dtxt.println(" sell @"+sell[0]+" x"+sell[1] - // +" buy @"+buy[0]+" x"+buy[1] - // +" => x"+count+" @"+unitprofit); + // debuglog(" sell @"+sell[0]+" x"+sell[1] + // +" buy @"+buy[0]+" x"+buy[1] + // +" => x"+count+" @"+unitprofit); if (unitprofit <= 0) break; @@ -1320,7 +1354,7 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { if (buy[1]==0) buys.remove(buy); if (sell[1]==0) sells.remove(sell); } - // if (dtxt!=null) dtxt.println(" PROFIT "+profit); + // debuglog(" PROFIT "+profit); return profit; } @@ -1333,7 +1367,8 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { } private @SuppressWarnings("unchecked") - void calculateArbitrage(ArrayList> data) { + void calculateArbitrage(ArrayList> data) + throws InterruptedException { int arbitrage = 0; ArrayList> arb_bs = null; String lastcommod = null; @@ -1341,15 +1376,15 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { for (ArrayList row : data) { String thiscommod = row.get(0); - // if (dtxt!=null) dtxt.println("ROW "+row.toString()); + // debuglog("ROW "+row.toString()); if (lastcommod == null || !thiscommod.equals(lastcommod)) { if (lastcommod != null) arbitrage += calculateArbitrageCommodity(arb_bs); - // if (dtxt!=null) dtxt.println("ROW rdy"); + // debuglog("ROW rdy"); arb_bs = new ArrayList>(2); arb_bs.add(0, new TreeSet(compar)); arb_bs.add(1, new TreeSet(compar)); - // if (dtxt!=null) dtxt.println("ROW init"); + // debuglog("ROW init"); lastcommod = thiscommod; } for (int bs = 0; bs < 2; bs++) { @@ -1357,19 +1392,23 @@ implements Runnable, TopLevelWindowListener, GUIInitializedListener { if (pricestr == null) continue; int[] entry = new int[2]; - // if (dtxt!=null) dtxt.println("ROW BS "+bs); + // debuglog("ROW BS "+bs); entry[0] = parseQty(pricestr); entry[1] = parseQty(row.get(bs*2 + 3)); arb_bs.get(bs).add(entry); } } arbitrage += calculateArbitrageCommodity(arb_bs); + String arb; if (arbitrage != 0) { - arbitrageResult.setText("arbitrage: "+arbitrage - +" poe"); + arb = "arbitrage: "+arbitrage+" poe"; } else { - arbitrageResult.setText("no arbitrage"); + arb = "no arbitrage"; } + final String arb_final = arb; + EventQueue.invokeLater(new Runnable() { public void run() { + arbitrageResult.setText(arb_final); + }}); } }