From: Ian Jackson Date: Sat, 2 Apr 2011 15:28:39 +0000 (+0100) Subject: formatting: reindent to 2 spaces, wrap lots of long lines; no intentional functional... X-Git-Tag: 1.0.5~12 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~yarrgweb/git?p=jarrg-ian.git;a=commitdiff_plain;h=5e6a57536036276ba15416c8fc894f78e34d73f5 formatting: reindent to 2 spaces, wrap lots of long lines; no intentional functional change --- diff --git a/src/net/chiark/yarrg/MarketUploader.java b/src/net/chiark/yarrg/MarketUploader.java index a6df497..4e04ee4 100644 --- a/src/net/chiark/yarrg/MarketUploader.java +++ b/src/net/chiark/yarrg/MarketUploader.java @@ -34,1179 +34,1279 @@ import java.beans.*; * an error dialog is shown, and processing returns, the button * becoming re-enabled. */ -public class MarketUploader implements Runnable, TopLevelWindowListener, GUIInitializedListener { - private JFrame frame = null; - private Window window = null; - private JButton findMarket = null; - private JLabel resultSummary = null; - private JLabel arbitrageResult = null; - private int unknownPCTBcommods = 0; - private long startTime = 0; - - 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 String PCTB_HOST_URL; - - // Yarrg protocol parameters - private final static String YARRG_CLIENTNAME = "jpctb greenend"; - private final static String YARRG_CLIENTVERSION = +public class MarketUploader +implements Runnable, TopLevelWindowListener, GUIInitializedListener { + private JFrame frame = null; + private Window window = null; + private JButton findMarket = null; + private JLabel resultSummary = null; + private JLabel arbitrageResult = null; + private int unknownPCTBcommods = 0; + private long startTime = 0; + + 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 String PCTB_HOST_URL; + + // Yarrg protocol parameters + private final static String YARRG_CLIENTNAME = "jpctb greenend"; + private final static String YARRG_CLIENTVERSION = net.chiark.yarrg.Version.version; - private final static String YARRG_CLIENTFIXES = "bug-094"; - private final static String YARRG_LIVE_URL = "http://upload.yarrg.chiark.net/commod-update-receiver"; - private final static String YARRG_TEST_URL = "http://upload.yarrg.chiark.net/test/commod-update-receiver"; - private String YARRG_URL; - - private boolean uploadToYarrg; - private boolean uploadToPCTB; - private boolean showArbitrage; - - private String islandName = null; - private String oceanName = null; - private java.util.concurrent.CountDownLatch latch = null; - - private AccessibleContext sidePanel; - 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(); - } - } - }; - - private int parseQty(String str) { - if (str.equals(">1000")) { - return 1001; - } else { - return Integer.parseInt(str); - } - } - - private void progresslog(String s) { - if (dtxt == null) return; - long now = new Date().getTime(); - dtxt.println("progress "+(now - startTime)+"ms "+s); - } - - private void debug_write_stringdata(String what, String data) throws FileNotFoundException,IOException { - if (dtxt==null) return; - PrintStream strm = new PrintStream(new File("jarrg-debug-"+what)); - strm.print(data); - strm.close(); - } - - private void debug_write_bytes(String what, byte[] data) throws FileNotFoundException,IOException { - if (dtxt==null) return; - FileOutputStream strm = new FileOutputStream(new File("jarrg-debug-"+what)); - strm.write(data); - strm.close(); - } - - private void progressNote(ProgressMonitor pm, String s) { - String arb = null; - if (arbitrageResult != null) - arb = arbitrageResult.getText(); - if (arb != null && arb.length() != 0) - s = "" + arb + "
" + s; - pm.setNote(s); + private final static String YARRG_CLIENTFIXES = "bug-094"; + private final static String YARRG_LIVE_URL = + "http://upload.yarrg.chiark.net/commod-update-receiver"; + private final static String YARRG_TEST_URL = + "http://upload.yarrg.chiark.net/test/commod-update-receiver"; + private String YARRG_URL; + + private boolean uploadToYarrg; + private boolean uploadToPCTB; + private boolean showArbitrage; + + private String islandName = null; + private String oceanName = null; + private java.util.concurrent.CountDownLatch latch = null; + + private AccessibleContext sidePanel; + 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(); } + } + }; + + private int parseQty(String str) { + if (str.equals(">1000")) { + return 1001; + } else { + return Integer.parseInt(str); + } + } + + private void progresslog(String s) { + if (dtxt == null) return; + long now = new Date().getTime(); + dtxt.println("progress "+(now - startTime)+"ms "+s); + } + + private void debug_write_stringdata(String what, String data) + throws FileNotFoundException,IOException { + if (dtxt==null) return; + PrintStream strm = new PrintStream(new File("jarrg-debug-"+what)); + strm.print(data); + strm.close(); + } + + private void debug_write_bytes(String what, byte[] data) + throws FileNotFoundException,IOException { + if (dtxt==null) return; + FileOutputStream strm = new FileOutputStream(new File("jarrg-debug-"+what)); + strm.write(data); + strm.close(); + } + + private void progressNote(ProgressMonitor pm, String s) { + String arb = null; + if (arbitrageResult != null) + arb = arbitrageResult.getText(); + if (arb != null && arb.length() != 0) + s = "" + arb + "
" + s; + pm.setNote(s); + } - /** - * An abstract market offer, entailing a commodity being bought or sold by - * a shoppe, for a certain price in a certain quantity. Not instantiable. - * - * @see Buy - * @see Sell - */ - abstract class Offer { - public int commodity, price, quantity, shoppe; - /** - * Create an offer from record, determining the shoppe Id from - * stallMap and the commodity Id from commodMap. - * priceIndex should be the index of the price in the record - * (the quantity will be priceIndex + 1). - * - * @param record the record with data to create the offer from - * @param stallMap a map containing the ids of the various stalls - * @param commodMap a map containing the ids of the various commodities - * @param priceIndex the index of the price in the record - */ - public Offer(ArrayList record, LinkedHashMap stallMap, HashMap commodMap, - int priceIndex) { - Integer commodId = commodMap.get(record.get(0)); - if(commodId == null) { - throw new IllegalArgumentException(); - } - commodity = commodId.intValue(); - price = Integer.parseInt(record.get(priceIndex)); - String qty = record.get(priceIndex+1); - quantity = parseQty(qty); - shoppe = stallMap.get(record.get(1)).intValue(); - } + /** + * An abstract market offer, entailing a commodity being bought or sold by + * a shoppe, for a certain price in a certain quantity. Not instantiable. + * + * @see Buy + * @see Sell + */ + abstract class Offer { + public int commodity, price, quantity, shoppe; + /** + * Create an offer from record, determining the shoppe Id from + * stallMap and the commodity Id from commodMap. + * priceIndex should be the index of the price in the record + * (the quantity will be priceIndex + 1). + * + * @param record the record with data to create the offer from + * @param stallMap a map containing the ids of the various stalls + * @param commodMap a map containing the ids of the various commodities + * @param priceIndex the index of the price in the record + */ + public Offer(ArrayList record, + LinkedHashMap stallMap, + HashMap commodMap, + int priceIndex) { + Integer commodId = commodMap.get(record.get(0)); + if(commodId == null) { + throw new IllegalArgumentException(); + } + commodity = commodId.intValue(); + price = Integer.parseInt(record.get(priceIndex)); + String qty = record.get(priceIndex+1); + quantity = parseQty(qty); + shoppe = stallMap.get(record.get(1)).intValue(); + } - /** - * Returns a human-readable version of this offer, useful for debugging - * - * @return human-readable offer - */ - public String toString() { - return "[C:" + commodity + ",$" + price + ",Q:" + quantity + ",S:" + shoppe + "]"; - } - } + /** + * Returns a human-readable version of this offer, useful for debugging + * + * @return human-readable offer + */ + public String toString() { + return "[C:" + commodity + ",$" + price + ",Q:" + + quantity + ",S:" + shoppe + "]"; + } + } - /** - * An offer from a shoppe or stall to buy a certain quantity of a commodity - * for a certain price. If placed in an ordered Set, sorts by commodity index ascending, - * then by buy price descending, and finally by stall id ascending. - */ - class Buy extends Offer implements Comparable { - /** - * Creates a new Buy offer from the given record - * using the other parameters to determine stall id and commodity id of the offer. - * - * @param record the record with data to create the offer from - * @param stallMap a map containing the ids of the various stalls - * @param commodMap a map containing the ids of the various commodities - */ - public Buy(ArrayList record, LinkedHashMap stallMap, HashMap commodMap) { - super(record,stallMap,commodMap,2); - } + /** + * An offer from a shoppe or stall to buy a certain quantity of a + * commodity for a certain price. If placed in an ordered Set, + * sorts by commodity index ascending, then by buy price + * descending, and finally by stall id ascending. + */ + class Buy extends Offer implements Comparable { + /** + * Creates a new Buy offer from the given + * record using the other parameters to determine + * stall id and commodity id of the offer. + * + * @param record the record with data to create the offer from + * @param stallMap a map containing the ids of the various stalls + * @param commodMap a map containing the ids of the various commodities + */ + public Buy(ArrayList record, + LinkedHashMap stallMap, + HashMap commodMap) { + super(record,stallMap,commodMap,2); + } - /** - * Sorts by commodity index ascending, then price descending, then stall id ascending. - */ - public int compareTo(Buy buy) { - // organize by: commodity index, price, stall index - if(commodity == buy.commodity) { - // organize by price, then by stall index - if(price == buy.price) { - // organize by stall index - return shoppe>buy.shoppe ? 1 : -1; - } else if(price > buy.price) { - return -1; - } else { - return 1; - } - } else if(commodity > buy.commodity) { - return 1; - } else { - return -1; - } - } + /** + * Sorts by commodity index ascending, then price descending, + * then stall id ascending. + */ + public int compareTo(Buy buy) { + // organize by: commodity index, price, stall index + if(commodity == buy.commodity) { + // organize by price, then by stall index + if(price == buy.price) { + // organize by stall index + return shoppe>buy.shoppe ? 1 : -1; + } else if(price > buy.price) { + return -1; + } else { + return 1; } + } else if(commodity > buy.commodity) { + return 1; + } else { + return -1; + } + } + } - /** - * An offer from a shoppe or stall to sell a certain quantity of a commodity - * for a certain price. If placed in an ordered Set, sorts by commodity index ascending, - * then by sell price ascending, and finally by stall id ascending. - */ - class Sell extends Offer implements Comparable { - /** - * Creates a new Sell offer from the given record - * using the other parameters to determine stall id and commodity id of the offer. - * - * @param record the record with data to create the offer from - * @param stallMap a map containing the ids of the various stalls - * @param commodMap a map containing the ids of the various commodities - */ - public Sell(ArrayList record, LinkedHashMap stallMap, HashMap commodMap) { - super(record,stallMap,commodMap,4); - } + /** + * An offer from a shoppe or stall to sell a certain quantity of + * a commodity for a certain price. If placed in an ordered Set, + * sorts by commodity index ascending, then by sell price + * ascending, and finally by stall id ascending. + */ + class Sell extends Offer implements Comparable { + /** + * Creates a new Sell offer from the given + * record using the other parameters to determine + * stall id and commodity id of the offer. + * + * @param record the record with data to create the offer from + * @param stallMap a map containing the ids of the various stalls + * @param commodMap a map containing the ids of the various commodities + */ + public Sell(ArrayList record, + LinkedHashMap stallMap, + HashMap commodMap) { + super(record,stallMap,commodMap,4); + } - /** - * Sorts by commodity index ascending, then price ascending, then stall id ascending. - */ - public int compareTo(Sell sell) { - // organize by: commodity index, price, stall index - if(commodity == sell.commodity) { - // organize by price, then by stall index - if(price == sell.price) { - // organize by stall index - return shoppe>sell.shoppe ? 1 : -1; - } else if(price > sell.price) { - return 1; - } else { - return -1; - } - } else if(commodity > sell.commodity) { - return 1; - } else { - return -1; - } - } + /** + * Sorts by commodity index ascending, then price ascending, then + * stall id ascending. + */ + public int compareTo(Sell sell) { + // organize by: commodity index, price, stall index + if(commodity == sell.commodity) { + // organize by price, then by stall index + if(price == sell.price) { + // organize by stall index + return shoppe>sell.shoppe ? 1 : -1; + } else if(price > sell.price) { + return 1; + } else { + return -1; } + } else if(commodity > sell.commodity) { + return 1; + } else { + return -1; + } + } + } - /** - * Entry point. Read our preferences. - */ - public MarketUploader() { - Preferences prefs = Preferences.userNodeForPackage(getClass()); - - if (prefs.getBoolean("writeDebugFiles", false)) { - try { - dtxt = new PrintStream(new File("jarrg-debug-log.txt")); - } catch (java.io.FileNotFoundException e) { - System.err.println("JARRG: Error opening debug log: "+e); - } - } + /** + * Entry point. Read our preferences. + */ + public MarketUploader() { + Preferences prefs = Preferences.userNodeForPackage(getClass()); + + if (prefs.getBoolean("writeDebugFiles", false)) { + try { + dtxt = new PrintStream(new File("jarrg-debug-log.txt")); + } catch (java.io.FileNotFoundException e) { + System.err.println("JARRG: Error opening debug log: "+e); + } + } - if (prefs.getBoolean("useLiveServers", true)) { - YARRG_URL = YARRG_LIVE_URL; - PCTB_HOST_URL = PCTB_LIVE_HOST_URL; - } else { - YARRG_URL = YARRG_TEST_URL; - PCTB_HOST_URL = PCTB_TEST_HOST_URL; - } + if (prefs.getBoolean("useLiveServers", true)) { + YARRG_URL = YARRG_LIVE_URL; + PCTB_HOST_URL = PCTB_LIVE_HOST_URL; + } else { + YARRG_URL = YARRG_TEST_URL; + PCTB_HOST_URL = PCTB_TEST_HOST_URL; + } - uploadToYarrg=prefs.getBoolean("uploadToYarrg", true); - uploadToPCTB=prefs.getBoolean("uploadToPCTB", true); - showArbitrage=prefs.getBoolean("showArbitrage", true); - - if (dtxt!=null) dtxt.println("main on dispatch thread: "+EventQueue.isDispatchThread()); - EventQueue.invokeLater(this); - } - - /* - * We arrange to wait for the GUI to be initialised, then look at every top-level window, - * and if it - */ - public void run() { - if (dtxt!=null) dtxt.println("MarketUploader run()..."); - if (EventQueueMonitor.isGUIInitialized()) { - if (dtxt!=null) dtxt.println("MarketUploader GUI already ready"); - guiInitialized(); - } else { - if (dtxt!=null) dtxt.println("MarketUploader waiting for GUI"); - EventQueueMonitor.addGUIInitializedListener(this); - } - } - - public void guiInitialized() { - Window ws[]= EventQueueMonitor.getTopLevelWindows(); - EventQueueMonitor.addTopLevelWindowListener(this); - for (int i=0; imsg. - * - * @param msg a String describing the error that occured. - */ - private void error(String msg) { - JOptionPane.showMessageDialog(frame,msg,"Error",JOptionPane.ERROR_MESSAGE); + frame.pack(); + } + + /** + * Finds the island name from the /who tab, sets global islandName variable + */ + private void getIsland() { + + // If the league tracker is there, we can skip the faff + // and ask for its tooltip, since we're on a boat + + Accessible leagueTrackerContainer = + descendNodes(window,new int[] {0,1,0,0,2,1}); + Accessible leagueTrackerItself = + descendByClass(leagueTrackerContainer, + "com.threerings.yohoho.sea.client.LeagueTracker"); + Accessible leagueTracker = descend(leagueTrackerItself, 1); + try { + islandName = ((JLabel)leagueTracker).getToolTipText(); + } catch (NullPointerException e) { + // evidently we're actually on an island + + islandName = null; + AccessibleContext chatArea = + descendNodes(window,new int[] {0,1,0,0,0,2,0,0,2}) + .getAccessibleContext(); + // attach the property change listener to the outer sunshine + // panel if the "ahoy" tab is not active, otherwise attach it to + // the scroll panel in the "ahoy" tab. + if(!"com.threerings.piracy.client.AttentionListPanel". + equals(descendNodes(window,new int[] {0,1,0,0,2,2,0}) + .getClass().getCanonicalName())) { + sidePanel = descendNodes(window,new int[] {0,1,0,0,2,2}) + .getAccessibleContext(); + } else { + sidePanel = descendNodes(window,new int[] {0,1,0,0,2,2,0,0,0}) + .getAccessibleContext(); + } + sidePanel.addPropertyChangeListener(changeListener); + latch = new java.util.concurrent.CountDownLatch(1); + // make the Players Online ("/who") panel appear + AccessibleEditableText chat = chatArea.getAccessibleEditableText(); + chat.setTextContents("/w"); + int c = chatArea.getAccessibleAction().getAccessibleActionCount(); + for(int i=0;imsg. + * + * @param msg a String describing the error that occured. + */ + private void error(String msg) { + JOptionPane.showMessageDialog(frame,msg,"Error",JOptionPane.ERROR_MESSAGE); + } - private void error_html(String msg, String html) { - Pattern body = Pattern.compile("(.*)", Pattern.DOTALL | Pattern.CASE_INSENSITIVE); - Matcher m = body.matcher(html); - if (m.find()) { - html = m.group(1); - Pattern fixup = Pattern.compile("<(\\w+) */>");; - m = fixup.matcher(html); - html = m.replaceAll("<$1>"); - m = Pattern.compile("[\\r\\n]+").matcher(html); - html = m.replaceAll(" "); - } - String whole_msg = "

Error

"+msg+"

PCTB Server said:

"+html+"
"; - if (dtxt!=null) dtxt.println("###" + whole_msg + "###"); + private void error_html(String msg, String html) { + Pattern body = Pattern.compile("(.*)", + Pattern.DOTALL | Pattern.CASE_INSENSITIVE); + Matcher m = body.matcher(html); + if (m.find()) { + html = m.group(1); + Pattern fixup = Pattern.compile("<(\\w+) */>");; + m = fixup.matcher(html); + html = m.replaceAll("<$1>"); + m = Pattern.compile("[\\r\\n]+").matcher(html); + html = m.replaceAll(" "); + } + String whole_msg = "

Error

"+msg + +"

PCTB Server said:

"+html+"
"; + if (dtxt!=null) dtxt.println("###" + whole_msg + "###"); - JOptionPane.showMessageDialog(frame,whole_msg,"Error",JOptionPane.ERROR_MESSAGE); - } + JOptionPane.showMessageDialog(frame,whole_msg,"Error", + JOptionPane.ERROR_MESSAGE); + } - /** - * Run the data collection process, and upload the results. This is the method - * that calls most of the other worker methods for the process. If an error occurs, - * the method will call the error method and return early, freeing up the button - * to be clicked again. - * - * @exception Exception if an error we didn't expect occured - */ - private class YarrgTimestampFetcher extends Thread { - public String ts = null; - public void run() { - try { - ts = getYarrgTimestamp(); - progresslog("(async) yarrg timestamp ready."); - } catch(Exception e) { - error("Error getting YARRG timestamp: "+e); - } - } - }; + /** + * Run the data collection process, and upload the results. This + * is the method that calls most of the other worker methods for + * the process. If an error occurs, the method will call the + * error method and return early, freeing up the button to be + * clicked again. + * + * @exception Exception if an error we didn't expect occured + */ + private class YarrgTimestampFetcher extends Thread { + public String ts = null; + public void run() { + try { + ts = getYarrgTimestamp(); + progresslog("(async) yarrg timestamp ready."); + } catch(Exception e) { + error("Error getting YARRG timestamp: "+e); + } + } + }; + + private void runUpload() throws Exception { + progresslog("starting"); + + ProgressMonitor pm = new ProgressMonitor + (frame,"Processing Market Data","Getting table data",0,100); + pm.setMillisToDecideToPopup(0); + pm.setMillisToPopup(0); + boolean doneyarrg = false, donepctb = false; + YarrgTimestampFetcher yarrgts_thread = null; + + if (uploadToYarrg) { + progresslog("(async) yarrg timestamp..."); + yarrgts_thread = new YarrgTimestampFetcher(); + yarrgts_thread.start(); + } - private void runUpload() throws Exception { - progresslog("starting"); + AccessibleTable accesstable = findMarketTable(); + if(accesstable == null) { + error("Market table not found!"+ + " Please open the Buy/Sell Commodities interface."); + return; + } + if(accesstable.getAccessibleRowCount() == 0) { + error("No data found, please wait for the table to have data first!"); + return; + } + if(!isDisplayAll()) { + error("Please select \"All\" from the Display: popup menu."); + return; + } - ProgressMonitor pm = new ProgressMonitor(frame,"Processing Market Data","Getting table data",0,100); - pm.setMillisToDecideToPopup(0); - pm.setMillisToPopup(0); - boolean doneyarrg = false, donepctb = false; - YarrgTimestampFetcher yarrgts_thread = null; + progresslog("(async) getisland..."); + getIsland(); + progresslog("getocean..."); + getOcean(); + progresslog("getocean done"); - if (uploadToYarrg) { - progresslog("(async) yarrg timestamp..."); - yarrgts_thread = new YarrgTimestampFetcher(); - yarrgts_thread.start(); - } + if (latch != null) { + latch.await(2, java.util.concurrent.TimeUnit.SECONDS); + } + progresslog("(async) getisland done"); + + String yarrgts = null; + if (yarrgts_thread != null) { + progresslog("(async) yarrg timestamp join..."); + yarrgts_thread.join(); + progresslog("(async) yarrg timestamp joined."); + yarrgts = yarrgts_thread.ts; + } - AccessibleTable accesstable = findMarketTable(); - if(accesstable == null) { - error("Market table not found! Please open the Buy/Sell Commodities interface."); - return; - } - if(accesstable.getAccessibleRowCount() == 0) { - error("No data found, please wait for the table to have data first!"); - return; - } - if(!isDisplayAll()) { - error("Please select \"All\" from the Display: popup menu."); - return; - } + if (islandName == null) { + error("Could not find island name in YPP user interface."); + return; + } - progresslog("(async) getisland..."); - getIsland(); - progresslog("getocean..."); - getOcean(); - progresslog("getocean done"); + progresslog("table check..."); - if (latch != null) { - latch.await(2, java.util.concurrent.TimeUnit.SECONDS); - } - progresslog("(async) getisland done"); - - String yarrgts = null; - if (yarrgts_thread != null) { - progresslog("(async) yarrg timestamp join..."); - yarrgts_thread.join(); - progresslog("(async) yarrg timestamp joined."); - yarrgts = yarrgts_thread.ts; - } + String headings_expected[] = new String[] + { "Commodity", "Trading outlet", "Buy price", + "Will buy", "Sell price", "Will sell" }; + ArrayList> headers = + getData(accesstable.getAccessibleColumnHeader()); + if (headers.size() != 1) { + error("Table headings not one row! " + headers.toString()); + return; + } + if (headers.get(0).size() < 6 || + headers.get(0).size() > 7) { + error("Table headings not six or seven columns! " + headers.toString()); + return; + } + for (int col=0; col> data = getData(accesstable); - String headings_expected[] = new String[] - { "Commodity", "Trading outlet", "Buy price", "Will buy", "Sell price", "Will sell" }; - ArrayList> headers = getData(accesstable.getAccessibleColumnHeader()); - if (headers.size() != 1) { - error("Table headings not one row! " + headers.toString()); - return; - } - if (headers.get(0).size() < 6 || - headers.get(0).size() > 7) { - error("Table headings not six or seven columns! " + headers.toString()); - return; - } - for (int col=0; col> data = getData(accesstable); + StringBuilder yarrgsb = new StringBuilder(); + String yarrgdata; // string containing what we'll feed to yarrg + + for (ArrayList row : data) { + if (row.size() > 6) { + row.remove(6); + } + for (String rowitem : row) { + yarrgsb.append(rowitem != null ? rowitem : ""); + yarrgsb.append("\t"); + } + yarrgsb.setLength(yarrgsb.length()-1); // chop + yarrgsb.append("\n"); + } - if (showArbitrage) { - progresslog("arbitrage..."); - calculateArbitrage(data); - progresslog("arbitrage done."); - } + yarrgdata = yarrgsb.toString(); - if (uploadToYarrg && yarrgts != null) { - progresslog("yarrg prepare..."); - progressNote(pm, "Yarrg: Preparing data"); - pm.setProgress(10); + progressNote(pm, "Yarrg: Uploading"); + progresslog("yarrg upload..."); - StringBuilder yarrgsb = new StringBuilder(); - String yarrgdata; // string containing what we'll feed to yarrg - - for (ArrayList row : data) { - if (row.size() > 6) { - row.remove(6); - } - for (String rowitem : row) { - yarrgsb.append(rowitem != null ? rowitem : ""); - yarrgsb.append("\t"); - } - yarrgsb.setLength(yarrgsb.length()-1); // chop - yarrgsb.append("\n"); - } - - yarrgdata = yarrgsb.toString(); - - progressNote(pm, "Yarrg: Uploading"); - progresslog("yarrg upload..."); - - doneyarrg = runYarrg(yarrgts, oceanName, islandName, yarrgdata); - progresslog("yarrg done."); - } + doneyarrg = runYarrg(yarrgts, oceanName, islandName, yarrgdata); + progresslog("yarrg done."); + } - if (uploadToPCTB) { - progresslog("pctb prepare..."); - progressNote(pm, "PCTB: Getting stall names"); - pm.setProgress(20); - if(pm.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()) { - return; - } - // get commod map + if (uploadToPCTB) { + progresslog("pctb prepare..."); + progressNote(pm, "PCTB: Getting stall names"); + pm.setProgress(20); + if(pm.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()) { + return; + } + // get commod map - progresslog("pctb commodmap..."); - HashMap commodMap = getCommodMap(); - if(commodMap == null) { - return; - } - progresslog("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); - - ByteArrayOutputStream outStream = new ByteArrayOutputStream(); - pm.setProgress(60); - progressNote(pm, "PCTB: Sending data"); - if(pm.isCanceled()) { - return; - } - GZIPOutputStream out = new GZIPOutputStream(outStream); - DataOutputStream dos = new DataOutputStream(out); - dos.writeBytes("005y\n"); - dos.writeBytes(stallMap.size()+"\n"); - dos.writeBytes(getAbbrevStallList(stallMap)); - writeBuySellOffers(buys,sells,offerCount,out); - out.finish(); - progresslog("pctb send..."); - - byte[] ba = outStream.toByteArray(); - debug_write_bytes("pctb-marketdata.gz", ba); - - InputStream in = sendInitialData(new ByteArrayInputStream(ba)); - progresslog("pctb sent."); - if (in == null) return; - pm.setProgress(80); - if(pm.isCanceled()) { - return; - } - progressNote(pm, "PCTB: Waiting ..."); - progresslog("pctb finish..."); - donepctb = finishUpload(in); - progresslog("pctb done."); - } - pm.setProgress(100); - - if ((uploadToPCTB && !donepctb) || - (uploadToYarrg && !doneyarrg)) { - resultSummary.setText("trouble"); - } else if (unknownPCTBcommods != 0) { - resultSummary.setText("PCTB lacks "+unknownPCTBcommods+" commod"); - } else if (donepctb || doneyarrg) { - resultSummary.setText("Done " + islandName); - } else { - resultSummary.setText("uploaded nowhere!"); - } - progresslog("done."); - } + progresslog("pctb commodmap..."); + HashMap commodMap = getCommodMap(); + if(commodMap == null) { + return; + } + progresslog("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); + + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + pm.setProgress(60); + progressNote(pm, "PCTB: Sending data"); + if(pm.isCanceled()) { + return; + } + GZIPOutputStream out = new GZIPOutputStream(outStream); + DataOutputStream dos = new DataOutputStream(out); + dos.writeBytes("005y\n"); + dos.writeBytes(stallMap.size()+"\n"); + dos.writeBytes(getAbbrevStallList(stallMap)); + writeBuySellOffers(buys,sells,offerCount,out); + out.finish(); + progresslog("pctb send..."); + + byte[] ba = outStream.toByteArray(); + debug_write_bytes("pctb-marketdata.gz", ba); + + InputStream in = sendInitialData(new ByteArrayInputStream(ba)); + progresslog("pctb sent."); + if (in == null) return; + pm.setProgress(80); + if(pm.isCanceled()) { + return; + } + progressNote(pm, "PCTB: Waiting ..."); + progresslog("pctb finish..."); + donepctb = finishUpload(in); + progresslog("pctb done."); + } + pm.setProgress(100); + + if ((uploadToPCTB && !donepctb) || + (uploadToYarrg && !doneyarrg)) { + resultSummary.setText("trouble"); + } else if (unknownPCTBcommods != 0) { + resultSummary.setText("PCTB lacks "+unknownPCTBcommods+" commod"); + } else if (donepctb || doneyarrg) { + resultSummary.setText("Done " + islandName); + } else { + resultSummary.setText("uploaded nowhere!"); + } + progresslog("done."); + } - /** - * Get the offer data out of the table and cache it in an ArrayList. - * - * @param table the AccessibleTable containing the market data - * @return an array of record arrays, each representing a row of the table - */ - private ArrayList> getData(AccessibleTable table) { - ArrayList> data = new ArrayList>(); - for (int i = 0; i < table.getAccessibleRowCount(); i++) { - ArrayList row = new ArrayList(); - for (int j = 0; j < table.getAccessibleColumnCount(); j++) { - row.add(table.getAccessibleAt(i, j).getAccessibleContext().getAccessibleName()); - } - data.add(row); - } - return data; - } + /** + * Get the offer data out of the table and cache it in an + * ArrayList. + * + * @param table the AccessibleTable containing the market data + * @return an array of record arrays, each representing a row of the table + */ + private ArrayList> getData(AccessibleTable table) { + ArrayList> data = new ArrayList>(); + for (int i = 0; i < table.getAccessibleRowCount(); i++) { + ArrayList row = new ArrayList(); + for (int j = 0; j < table.getAccessibleColumnCount(); j++) { + row.add(table.getAccessibleAt(i, j) + .getAccessibleContext().getAccessibleName()); + } + data.add(row); + } + return data; + } - /** - * @return the table containing market data if it exists, otherwise null - */ - public AccessibleTable findMarketTable() { - 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); - 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); - return table; - } + /** + * @return the table containing market data if it exists, + * otherwise null + */ + public AccessibleTable findMarketTable() { + 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); + 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); + return table; + } - /** - * Utility method to descend through several levels of Accessible children - * at once. - * - * @param parent the node on which to start the descent - * @param path an array of ints, each int being the index of the next - * accessible child to descend. - * @return the Accessible reached by following the descent path, - * or null if the desired path was invalid. - */ - private Accessible descendNodes(Accessible parent, int[] path) { - for(int i=0;iAccessible reached by following the + * descent path, or null if the desired path was + * invalid. + */ + private Accessible descendNodes(Accessible parent, int[] path) { + for(int i=0;iAccessible "node". - * - * @param parent the node with children - * @param childNum the index of the child of parent to return - * @return the childNum child of parent or null - * if the child is not found. - */ - private Accessible descend(Accessible parent, int childNum) { - if (parent == null) return null; - int children = parent.getAccessibleContext().getAccessibleChildrenCount(); - if (childNum >= children) { - if (dtxt!=null) dtxt.println("DESCEND "+childNum+" > "+children+" NOT FOUND"); - return null; - } - Accessible child = parent.getAccessibleContext().getAccessibleChild(childNum); - if (dtxt!=null) dtxt.println("DESCEND "+childNum+" "+child.getClass().getName()+" OK"); - return child; - } - - /** - * Descends one level to the child which has the specified class. - * - * @param parent the node with children - * @param classname the name of the class, as a string - * @return the child or null if the child is not found. - */ - private Accessible descendByClass(Accessible parent, String classname) { - if (parent == null) return null; - AccessibleContext ac = parent.getAccessibleContext(); - int children = ac.getAccessibleChildrenCount(); - for (int i=0; itrue if all commodities are displayed, otherwise false - */ - private boolean isDisplayAll() { - 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}); - } - String display = button.getAccessibleContext().getAccessibleName(); - if(!display.equals("All")) { - return false; - } - return true; - } + /** + * Descends one level to the specified child of the parent + * Accessible "node". + * + * @param parent the node with children + * @param childNum the index of the child of parent to return + * @return the childNum child of parent + * or null if the child is not found. + */ + private Accessible descend(Accessible parent, int childNum) { + if (parent == null) return null; + int children = parent.getAccessibleContext().getAccessibleChildrenCount(); + if (childNum >= children) { + if (dtxt!=null) dtxt.println("DESCEND "+childNum+" > " + +children+" NOT FOUND"); + return null; + } + Accessible child = parent.getAccessibleContext() + .getAccessibleChild(childNum); + if (dtxt!=null) dtxt.println("DESCEND "+childNum+" " + +child.getClass().getName()+" OK"); + return child; + } + + /** + * Descends one level to the child which has the specified class. + * + * @param parent the node with children + * @param classname the name of the class, as a string + * @return the child or null if the child is not found. + */ + private Accessible descendByClass(Accessible parent, String classname) { + if (parent == null) return null; + AccessibleContext ac = parent.getAccessibleContext(); + int children = ac.getAccessibleChildrenCount(); + for (int i=0; itrue if all commodities are displayed, + * otherwise false + */ + private boolean isDisplayAll() { + 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}); + } + String display = button.getAccessibleContext().getAccessibleName(); + if(!display.equals("All")) { + return false; + } + return true; + } - /** - * Gets the list of commodities and their associated commodity ids. - * - * @return a map where the key is the commodity and the value is the commodity id. - */ - private HashMap getCommodMap() { - if(commodMap != null) { - return commodMap; - } - HashMap map = new HashMap(); - String xml; - try { - URL host = new URL(PCTB_HOST_URL + "commodmap.php"); - BufferedReader br = new BufferedReader(new InputStreamReader(host.openStream())); - StringBuilder sb = new StringBuilder(); - String str; - while((str = br.readLine()) != null) { - sb.append(str); - } - if (dtxt != null) debug_write_stringdata("pctb-commodmap.xmlish", sb.toString()); - int first = sb.indexOf("
") + 5;
-			int last = sb.indexOf("");
-			xml = sb.substring(first,last);
-			Reader reader = new CharArrayReader(xml.toCharArray());
-			Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(reader));
-			NodeList maps = d.getElementsByTagName("CommodMap");
-			for(int i=0;i getCommodMap() {
+    if(commodMap != null) {
+      return commodMap;
+    }
+    HashMap map = new HashMap();
+    String xml;
+    try {
+      URL host = new URL(PCTB_HOST_URL + "commodmap.php");
+      BufferedReader br =
+	new BufferedReader(new InputStreamReader(host.openStream()));
+      StringBuilder sb = new StringBuilder();
+      String str;
+      while((str = br.readLine()) != null) {
+	sb.append(str);
+      }
+      if (dtxt != null)
+	debug_write_stringdata("pctb-commodmap.xmlish", sb.toString());
+      int first = sb.indexOf("
") + 5;
+      int last = sb.indexOf("");
+      xml = sb.substring(first,last);
+      Reader reader = new CharArrayReader(xml.toCharArray());
+      Document d = DocumentBuilderFactory.newInstance()
+	.newDocumentBuilder().parse(new InputSource(reader));
+      NodeList maps = d.getElementsByTagName("CommodMap");
+      for(int i=0;iLinkedHashMap where the key is the stall name
-	*	and the value is the generated stall id (position in the list).
-	*	

- * The reason this method returns a LinkedHashMap instead of a simple HashMap is the need - * for iterating over the stall names in insertion order for output to the server. - * - * @param offers the list of records from the commodity buy/sell interface - * @return an iterable ordered map of the stall names and generated stall ids - */ - private LinkedHashMap getStallMap(ArrayList> offers) { - int count = 0; - LinkedHashMap map = new LinkedHashMap(); - for(ArrayList offer : offers) { - String shop = offer.get(1); - if(!map.containsKey(shop)) { - count++; - map.put(shop,count); - } - } - return map; - } + /** + * Given the list of offers, this method will find all the unique + * stall names and return them in a LinkedHashMap + * where the key is the stall name and the value is the generated + * stall id (position in the list).

The reason this method + * returns a LinkedHashMap instead of a simple HashMap is the + * need for iterating over the stall names in insertion order for + * output to the server. + * + * @param offers the list of records from the commodity buy/sell interface + * @return an iterable ordered map of the stall names and + * generated stall ids + */ + private LinkedHashMap getStallMap + (ArrayList> offers) { + int count = 0; + LinkedHashMap map = new LinkedHashMap(); + for(ArrayList offer : offers) { + String shop = offer.get(1); + if(!map.containsKey(shop)) { + count++; + map.put(shop,count); + } + } + return map; + } - /** - * Gets a sorted list of Buys and Sells from the list of records. buys and sells - * should be pre-initialized and passed into the method to receive the data. - * Returns a 2-length int array with the number of buys and sells found. - * - * @param offers the data found from the market table in-game - * @param buys an empty initialized TreeSet<Offer> to - * hold the Buy offers. - * @param sells an empty initialized TreeSet<Offer> to - * hold the Sell offers. - * @param stalls the map of stalls to their ids - * @param commodMap the map of commodities to their ids - * @return a 2-length int[] array containing the number of buys and sells, respectively - */ - private int[] getBuySellMaps(ArrayList> offers, TreeSet buys, - TreeSet sells, LinkedHashMap stalls, HashMap commodMap) { - int[] buySellCount = new int[2]; - for(ArrayList offer : offers) { - try { - if(offer.get(2) != null) { - buys.add(new Buy(offer,stalls,commodMap)); - buySellCount[0]++; - } - if(offer.get(4) != null) { - sells.add(new Sell(offer,stalls,commodMap)); - buySellCount[1]++; - } - } catch(IllegalArgumentException e) { - unknownPCTBcommods++; - if (dtxt!=null) dtxt.println("Error: Unsupported Commodity \"" + offer.get(0) + "\""); - } - } - if (buySellCount[0]==0 && buySellCount[1]==0) { - error("No (valid) offers for PCTB?!"); - throw new IllegalArgumentException(); - } - return buySellCount; + /** + * Gets a sorted list of Buys and Sells from the list of + * records. buys and sells should be + * pre-initialized and passed into the method to receive the + * data. Returns a 2-length int array with the number of buys + * and sells found. + * + * @param offers the data found from the market table in-game + * @param buys an empty initialized TreeSet<Offer> to + * hold the Buy offers. + * @param sells an empty initialized TreeSet<Offer> to + * hold the Sell offers. + * @param stalls the map of stalls to their ids + * @param commodMap the map of commodities to their ids + * @return a 2-length int[] array containing the number of buys + * and sells, respectively + */ + private int[] getBuySellMaps(ArrayList> offers, + TreeSet buys, + TreeSet sells, + LinkedHashMap stalls, + HashMap commodMap) { + int[] buySellCount = new int[2]; + for(ArrayList offer : offers) { + try { + if(offer.get(2) != null) { + buys.add(new Buy(offer,stalls,commodMap)); + buySellCount[0]++; + } + if(offer.get(4) != null) { + sells.add(new Sell(offer,stalls,commodMap)); + buySellCount[1]++; } + } catch(IllegalArgumentException e) { + unknownPCTBcommods++; + if (dtxt!=null) dtxt.println("Error: Unsupported Commodity \"" + + offer.get(0) + "\""); + } + } + if (buySellCount[0]==0 && buySellCount[1]==0) { + error("No (valid) offers for PCTB?!"); + throw new IllegalArgumentException(); + } + return buySellCount; + } - /** - * Prepares the list of stalls for writing to the output stream. - * The String returned by this method is ready to be written - * directly to the stream. - *

- * All shoppe names are left as they are. Stall names are abbreviated just before the - * apostrophe in the possessive, with an "^" and a letter matching the stall's type - * appended. Example: "Burninator's Ironworking Stall" would become "Burninator^I". - * - * @param stallMap the map of stalls and stall ids in an iterable order - * @return a String containing the list of stalls in format ready - * to be written to the output stream. - */ - private String getAbbrevStallList(LinkedHashMap stallMap) { - // set up some mapping - HashMap types = new HashMap(); - types.put("Apothecary Stall", "A"); - types.put("Distilling Stall", "D"); - types.put("Furnishing Stall", "F"); - types.put("Ironworking Stall", "I"); - types.put("Shipbuilding Stall", "S"); - types.put("Tailoring Stall", "T"); - types.put("Weaving Stall", "W"); + /** + * Prepares the list of stalls for writing to the output stream. + * The String returned by this method is ready to be + * written directly to the stream.

All shoppe names are left + * as they are. Stall names are abbreviated just before the + * apostrophe in the possessive, with an "^" and a letter + * matching the stall's type appended. Example: "Burninator's + * Ironworking Stall" would become "Burninator^I". + * + * @param stallMap the map of stalls and stall ids in an iterable order + * @return a String containing the list of stalls in + * format ready to be written to the output stream. + */ + private String getAbbrevStallList(LinkedHashMap stallMap) { + // set up some mapping + HashMap types = new HashMap(); + types.put("Apothecary Stall", "A"); + types.put("Distilling Stall", "D"); + types.put("Furnishing Stall", "F"); + types.put("Ironworking Stall", "I"); + types.put("Shipbuilding Stall", "S"); + types.put("Tailoring Stall", "T"); + types.put("Weaving Stall", "W"); - StringBuilder sb = new StringBuilder(); - for(String name : stallMap.keySet()) { - int index = name.indexOf("'s"); - String finalName = name; - String type = null; - if (index > 0) { - finalName = name.substring(0,index); - if(index + 2 < name.length()) { - String end = name.substring(index+2,name.length()).trim(); - type = types.get(end); - } - } - if(type==null) { - sb.append(name+"\n"); - } else { - sb.append(finalName+"^"+type+"\n"); - } - } - return sb.toString(); + StringBuilder sb = new StringBuilder(); + for(String name : stallMap.keySet()) { + int index = name.indexOf("'s"); + String finalName = name; + String type = null; + if (index > 0) { + finalName = name.substring(0,index); + if(index + 2 < name.length()) { + String end = name.substring(index+2,name.length()).trim(); + type = types.get(end); } + } + if(type==null) { + sb.append(name+"\n"); + } else { + sb.append(finalName+"^"+type+"\n"); + } + } + return sb.toString(); + } - /** - * Writes a list of offers in correct format to the output stream. - *

- * The format is thus: (all numbers are 2-byte integers in little-endian format) - * (number of offers of this type, aka buy/sell) - * (commodity ID) (number of offers for this commodity) [shopID price qty][shopID price qty]... - * - * @param out the output stream to write the data to - * @param offers the offers to write - */ - private void writeOffers(OutputStream out, TreeSet offers) throws IOException { - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - if(offers.size() == 0) { - // nothing to write, and "0" has already been written - return; - } - int commodity = offers.first().commodity; - int count = 0; - for(Offer offer : offers) { - if(commodity != offer.commodity) { - // write out buffer - writeBufferedOffers(out,buffer.toByteArray(),commodity,count); - buffer.reset(); - commodity = offer.commodity; - count = 0; - } - writeLEShort(offer.shoppe,buffer); // stall index - writeLEShort(offer.price,buffer); // buy price - writeLEShort(offer.quantity,buffer); // buy qty - count++; - } - writeBufferedOffers(out,buffer.toByteArray(),commodity,count); - } + /** + * Writes a list of offers in correct format to the output stream. + *

+ * The format is thus: (all numbers are 2-byte integers in + * little-endian format) (number of offers of this type, aka + * buy/sell) (commodity ID) (number of offers for this commodity) + * [shopID price qty][shopID price qty]... + * + * @param out the output stream to write the data to + * @param offers the offers to write + */ + private void writeOffers(OutputStream out, TreeSet offers) + throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + if(offers.size() == 0) { + // nothing to write, and "0" has already been written + return; + } + int commodity = offers.first().commodity; + int count = 0; + for(Offer offer : offers) { + if(commodity != offer.commodity) { + // write out buffer + writeBufferedOffers(out,buffer.toByteArray(),commodity,count); + buffer.reset(); + commodity = offer.commodity; + count = 0; + } + writeLEShort(offer.shoppe,buffer); // stall index + writeLEShort(offer.price,buffer); // buy price + writeLEShort(offer.quantity,buffer); // buy qty + count++; + } + writeBufferedOffers(out,buffer.toByteArray(),commodity,count); + } - /** - * Writes the buffered data to the output strea for one commodity. - * - * @param out the stream to write to - * @param buffer the buffered data to write - * @param commodity the commmodity id to write before the buffered data - * @param count the number of offers for this commodity to write before the data - */ - private void writeBufferedOffers(OutputStream out, byte[] buffer, int commodity, int count) throws IOException { - writeLEShort(commodity,out); // commod index - writeLEShort(count,out); // offer count - out.write(buffer); // the buffered offers - } + /** + * Writes the buffered data to the output strea for one commodity. + * + * @param out the stream to write to + * @param buffer the buffered data to write + * @param commodity the commmodity id to write before the buffered data + * @param count the number of offers for this commodity to write + * before the data + */ + private void writeBufferedOffers(OutputStream out, byte[] buffer, + int commodity, int count) + throws IOException { + writeLEShort(commodity,out); // commod index + writeLEShort(count,out); // offer count + out.write(buffer); // the buffered offers + } - /** - * Writes the buy and sell offers to the outputstream by calling other methods. - * - * @param buys list of Buy offers to write - * @param sells list of Sell offers to write - * @param offerCount 2-length int array containing the number of buys and sells to write out - * @param out the stream to write to - */ - private void writeBuySellOffers(TreeSet buys, - TreeSet sells, int[] offerCount, OutputStream out) throws IOException { - // # buy offers - writeLEShort(offerCount[0],out); - writeOffers(out,buys); - // # sell offers - writeLEShort(offerCount[1],out); - writeOffers(out,sells); - } + /** + * Writes the buy and sell offers to the outputstream by calling + * other methods. + * + * @param buys list of Buy offers to write + * @param sells list of Sell offers to write + * @param offerCount 2-length int array containing the number of + * buys and sells to write out + * @param out the stream to write to + */ + private void writeBuySellOffers(TreeSet buys, + TreeSet sells, + int[] offerCount, OutputStream out) + throws IOException { + // # buy offers + writeLEShort(offerCount[0],out); + writeOffers(out,buys); + // # sell offers + writeLEShort(offerCount[1],out); + writeOffers(out,sells); + } - private String readstreamstring(InputStream in) throws IOException { - StringBuilder sb = new StringBuilder(); - BufferedReader br = new BufferedReader(new InputStreamReader(in)); - String str; - while((str = br.readLine()) != null) { - sb.append(str+"\n"); - } - return sb.toString(); - } - - /** - * Sends the data to the server via multipart-formdata POST, - * with the gzipped data as a file upload. - * - * @param file an InputStream open to the gzipped data we want to send - */ - private InputStream sendInitialData(InputStream file) throws IOException { - ClientHttpRequest http = new ClientHttpRequest(PCTB_HOST_URL + "upload.php"); - http.setParameter("marketdata","marketdata.gz",file,"application/gzip"); - if (!http.post()) { - String err = readstreamstring(http.resultstream()); - error("Error sending initial data:\n"+err); - return null; - } - return http.resultstream(); - } + private String readstreamstring(InputStream in) throws IOException { + StringBuilder sb = new StringBuilder(); + BufferedReader br = new BufferedReader(new InputStreamReader(in)); + String str; + while((str = br.readLine()) != null) { + sb.append(str+"\n"); + } + return sb.toString(); + } + + /** + * Sends the data to the server via multipart-formdata POST, + * with the gzipped data as a file upload. + * + * @param file an InputStream open to the gzipped data we want to send + */ + private InputStream sendInitialData(InputStream file) throws IOException { + ClientHttpRequest http = + new ClientHttpRequest(PCTB_HOST_URL + "upload.php"); + http.setParameter("marketdata","marketdata.gz",file,"application/gzip"); + if (!http.post()) { + String err = readstreamstring(http.resultstream()); + error("Error sending initial data:\n"+err); + return null; + } + return http.resultstream(); + } - /** - * Utility method to write a 2-byte int in little-endian form to an output stream. - * - * @param num an integer to write - * @param out stream to write to - */ - private void writeLEShort(int num, OutputStream out) throws IOException { - out.write(num & 0xFF); - out.write((num >>> 8) & 0xFF); - } + /** + * Utility method to write a 2-byte int in little-endian form to + * an output stream. + * + * @param num an integer to write + * @param out stream to write to + */ + private void writeLEShort(int num, OutputStream out) throws IOException { + out.write(num & 0xFF); + out.write((num >>> 8) & 0xFF); + } - /** - * Reads the response from the server, and selects the correct parameters - * which are sent in a GET request to the server asking it to confirm - * the upload and accept the data into the database. Notably, the island id - * and ocean id are determined, while other parameter such as the filename - * are determined from the hidden form fields. - * - * @param in stream of data from the server to read - */ - private boolean finishUpload(InputStream in) throws IOException { - String html = readstreamstring(in); - debug_write_stringdata("pctb-initial.html", html); - Matcher m; - - Pattern params = Pattern.compile("(?s).+?.+?"); - m = params.matcher(html); - if(!m.find()) { - error_html("The PCTB server returned unusual data. Maybe you're using an old version of the uploader?", - html); - return false; - } - String forceReload = m.group(1); - String filename = m.group(2); - - Pattern oceanNumPat = Pattern.compile(""); - m = oceanNumPat.matcher(html); - if (!m.find()) { - error_html("Unable to find the ocean in the server's list of oceans!", html); - return false; - } - String oceanNum = m.group(1); - - Pattern oceanIslandNum = Pattern.compile("islands\\[" + oceanNum + "\\]\\[\\d+\\]=new Option\\(\"" + islandName + "\",(\\d+)"); - m = oceanIslandNum.matcher(html); - if(!m.find()) { - error_html("This does not seem to be a valid island! Unable to upload.", html); - return false; - } - String islandNum = m.group(1); - - URL get = new URL(PCTB_HOST_URL + "upload.php?action=setisland&ocean=" + oceanNum + "&island=" - + islandNum + "&forcereload=" + forceReload + "&filename=" + filename); - String complete = readstreamstring(get.openStream()); - debug_write_stringdata("pctb-final.html", complete); - Pattern done = Pattern.compile("Your data has been integrated into the database. Thank you!"); - m = done.matcher(complete); - if(m.find()) { - return true; - } else { - error_html("Something was wrong with the final upload parameters!", complete); - return false; - } - } - - private InputStream post_for_yarrg(ClientHttpRequest http) throws IOException { - if (!http.post()) { - String err = readstreamstring(http.resultstream()); - error("

Error reported by YARRG server

\n" + err); - return null; - } - return http.resultstream(); + /** + * Reads the response from the server, and selects the correct parameters + * which are sent in a GET request to the server asking it to confirm + * the upload and accept the data into the database. Notably, the island id + * and ocean id are determined, while other parameter such as the filename + * are determined from the hidden form fields. + * + * @param in stream of data from the server to read + */ + private boolean finishUpload(InputStream in) throws IOException { + String html = readstreamstring(in); + debug_write_stringdata("pctb-initial.html", html); + Matcher m; + + Pattern params = Pattern.compile + ("(?s)"+ + ".+?"+ + ".+?"); + m = params.matcher(html); + if(!m.find()) { + error_html("The PCTB server returned unusual data."+ + " Maybe you're using an old version of the uploader?", + html); + return false; } - - private String getYarrgTimestamp() throws IOException { - ClientHttpRequest http = new ClientHttpRequest (YARRG_URL); - http.setParameter("clientname", YARRG_CLIENTNAME); - http.setParameter("clientversion", YARRG_CLIENTVERSION); - http.setParameter("clientfixes", YARRG_CLIENTFIXES); - http.setParameter("requesttimestamp", "y"); - InputStream in = post_for_yarrg(http); - if (in == null) return null; - BufferedReader br = new BufferedReader(new InputStreamReader(in)); - String tsresult = br.readLine(); - return tsresult.substring(3, tsresult.length()-1); + String forceReload = m.group(1); + String filename = m.group(2); + + Pattern oceanNumPat = + Pattern.compile(""); + m = oceanNumPat.matcher(html); + if (!m.find()) { + error_html("Unable to find the ocean in the server's list of oceans!", + html); + return false; } - - private boolean runYarrg(String timestamp, String ocean, String island, String yarrgdata) throws IOException { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - BufferedOutputStream bufos = new BufferedOutputStream(new GZIPOutputStream(bos)); - bufos.write(yarrgdata.getBytes() ); - bufos.close(); - byte[] compressed = bos.toByteArray(); - debug_write_bytes("yarrg-deduped.tsv.gz", compressed); - ByteArrayInputStream file = new ByteArrayInputStream(compressed); - - ClientHttpRequest http = new ClientHttpRequest (YARRG_URL); - http.setParameter("clientname", YARRG_CLIENTNAME); - http.setParameter("clientversion", YARRG_CLIENTVERSION); - http.setParameter("clientfixes", YARRG_CLIENTFIXES); - http.setParameter("timestamp", timestamp); - http.setParameter("ocean", ocean); - http.setParameter("island", island); - http.setParameter("data", "deduped.tsv.gz", file, "application/octet-stream"); - InputStream in = post_for_yarrg(http); - if (in == null) return false; - String output = readstreamstring(in); - if (!output.startsWith("OK")) { - error("

Unexpected output from YARRG server

\n" + output); - return false; - } - debug_write_stringdata("yarrg-result.txt", output); - return true; + String oceanNum = m.group(1); + + Pattern oceanIslandNum = + Pattern.compile("islands\\[" + oceanNum + + "\\]\\[\\d+\\]=new Option\\(\"" + islandName + + "\",(\\d+)"); + m = oceanIslandNum.matcher(html); + if(!m.find()) { + error_html("This does not seem to be a valid island! Unable to upload.", + html); + return false; } - - private int calculateArbitrageCommodity(ArrayList> arb_bs) { - // if (dtxt!=null) dtxt.println("ARBITRAGE?"); - int profit = 0; - SortedSet buys = arb_bs.get(0); - SortedSet sells = arb_bs.get(1); - while (true) { - int[] buy, sell; - try { - // NB "sell" means they sell, ie we buy - sell = sells.last(); - buy = buys.first(); - } catch (NoSuchElementException e) { - break; - } - - 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); - - if (unitprofit <= 0) - break; + String islandNum = m.group(1); + + URL get = new URL(PCTB_HOST_URL + + "upload.php?action=setisland&ocean=" + oceanNum + + "&island=" + islandNum + + "&forcereload=" + forceReload + + "&filename=" + filename); + String complete = readstreamstring(get.openStream()); + debug_write_stringdata("pctb-final.html", complete); + Pattern done = Pattern.compile + ("Your data has been integrated into the database. Thank you!"); + m = done.matcher(complete); + if(m.find()) { + return true; + } else { + error_html("Something was wrong with the final upload parameters!", + complete); + return false; + } + } + + private InputStream post_for_yarrg(ClientHttpRequest http) + throws IOException { + if (!http.post()) { + String err = readstreamstring(http.resultstream()); + error("

Error reported by YARRG server

\n" + err); + return null; + } + return http.resultstream(); + } + + private String getYarrgTimestamp() throws IOException { + ClientHttpRequest http = new ClientHttpRequest (YARRG_URL); + http.setParameter("clientname", YARRG_CLIENTNAME); + http.setParameter("clientversion", YARRG_CLIENTVERSION); + http.setParameter("clientfixes", YARRG_CLIENTFIXES); + http.setParameter("requesttimestamp", "y"); + InputStream in = post_for_yarrg(http); + if (in == null) return null; + BufferedReader br = new BufferedReader(new InputStreamReader(in)); + String tsresult = br.readLine(); + return tsresult.substring(3, tsresult.length()-1); + } + + private boolean runYarrg(String timestamp, String ocean, String island, + String yarrgdata) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + BufferedOutputStream bufos = + new BufferedOutputStream(new GZIPOutputStream(bos)); + bufos.write(yarrgdata.getBytes() ); + bufos.close(); + byte[] compressed = bos.toByteArray(); + debug_write_bytes("yarrg-deduped.tsv.gz", compressed); + ByteArrayInputStream file = new ByteArrayInputStream(compressed); + + ClientHttpRequest http = new ClientHttpRequest (YARRG_URL); + http.setParameter("clientname", YARRG_CLIENTNAME); + http.setParameter("clientversion", YARRG_CLIENTVERSION); + http.setParameter("clientfixes", YARRG_CLIENTFIXES); + http.setParameter("timestamp", timestamp); + http.setParameter("ocean", ocean); + http.setParameter("island", island); + http.setParameter("data", "deduped.tsv.gz", file, + "application/octet-stream"); + InputStream in = post_for_yarrg(http); + if (in == null) return false; + String output = readstreamstring(in); + if (!output.startsWith("OK")) { + error("

Unexpected output from YARRG server

\n" + output); + return false; + } + debug_write_stringdata("yarrg-result.txt", output); + return true; + } + + private int calculateArbitrageCommodity(ArrayList> arb_bs) { + // if (dtxt!=null) dtxt.println("ARBITRAGE?"); + int profit = 0; + SortedSet buys = arb_bs.get(0); + SortedSet sells = arb_bs.get(1); + while (true) { + int[] buy, sell; + try { + // NB "sell" means they sell, ie we buy + sell = sells.last(); + buy = buys.first(); + } catch (NoSuchElementException e) { + break; + } + + 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); + + if (unitprofit <= 0) + break; - profit += count * unitprofit; - buy[1] -= count; - sell[1] -= count; - if (buy[1]==0) buys.remove(buy); - if (sell[1]==0) sells.remove(sell); - } - // if (dtxt!=null) dtxt.println(" PROFIT "+profit); - return profit; + profit += count * unitprofit; + buy[1] -= count; + sell[1] -= count; + if (buy[1]==0) buys.remove(buy); + if (sell[1]==0) sells.remove(sell); } - - private class arbitrageOfferComparator implements Comparator { - public int compare(Object o1, Object o2) { - int p1 = ((int[])o1)[0]; - int p2 = ((int[])o2)[0]; - return p2 - p1; - } + // if (dtxt!=null) dtxt.println(" PROFIT "+profit); + return profit; + } + + private class arbitrageOfferComparator implements Comparator { + public int compare(Object o1, Object o2) { + int p1 = ((int[])o1)[0]; + int p2 = ((int[])o2)[0]; + return p2 - p1; } + } - private @SuppressWarnings("unchecked") + private @SuppressWarnings("unchecked") void calculateArbitrage(ArrayList> data) { - int arbitrage = 0; - ArrayList> arb_bs = null; - String lastcommod = null; - Comparator compar = new arbitrageOfferComparator(); - - for (ArrayList row : data) { - String thiscommod = row.get(0); - // if (dtxt!=null) dtxt.println("ROW "+row.toString()); - if (lastcommod == null || !thiscommod.equals(lastcommod)) { - if (lastcommod != null) - arbitrage += calculateArbitrageCommodity(arb_bs); - // if (dtxt!=null) dtxt.println("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"); - lastcommod = thiscommod; - } - for (int bs = 0; bs < 2; bs++) { - String pricestr = row.get(bs*2 + 2); - if (pricestr == null) - continue; - int[] entry = new int[2]; - // if (dtxt!=null) dtxt.println("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); - if (arbitrage != 0) { - arbitrageResult.setText("arbitrage: "+arbitrage+" poe"); - } else { - arbitrageResult.setText("no arbitrage"); - } + int arbitrage = 0; + ArrayList> arb_bs = null; + String lastcommod = null; + Comparator compar = new arbitrageOfferComparator(); + + for (ArrayList row : data) { + String thiscommod = row.get(0); + // if (dtxt!=null) dtxt.println("ROW "+row.toString()); + if (lastcommod == null || !thiscommod.equals(lastcommod)) { + if (lastcommod != null) + arbitrage += calculateArbitrageCommodity(arb_bs); + // if (dtxt!=null) dtxt.println("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"); + lastcommod = thiscommod; + } + for (int bs = 0; bs < 2; bs++) { + String pricestr = row.get(bs*2 + 2); + if (pricestr == null) + continue; + int[] entry = new int[2]; + // if (dtxt!=null) dtxt.println("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); + if (arbitrage != 0) { + arbitrageResult.setText("arbitrage: "+arbitrage + +" poe"); + } else { + arbitrageResult.setText("no arbitrage"); } + } }