X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~yarrgweb/git?p=jarrg-ian.git;a=blobdiff_plain;f=src%2Fcom%2Ftedpearson%2Fypp%2Fmarket%2FMarketUploader.java;h=98c5dd8808ecbe1b1c3c21c04811f33afd495520;hp=729c6869f4ffc2b658501115222b4a775faaa1ee;hb=b4fbcc4b1b6ac5c88c747fbd98b51935fe8150d6;hpb=78039ce424d4c4b5b9011b99e993ac7bd80a3a9c;ds=sidebyside diff --git a/src/com/tedpearson/ypp/market/MarketUploader.java b/src/com/tedpearson/ypp/market/MarketUploader.java index 729c686..98c5dd8 100644 --- a/src/com/tedpearson/ypp/market/MarketUploader.java +++ b/src/com/tedpearson/ypp/market/MarketUploader.java @@ -39,6 +39,8 @@ public class MarketUploader implements TopLevelWindowListener, GUIInitializedLis private Window window = null; private JButton findMarket = null; private JLabel resultSummary = null; + private JLabel arbitrageResult = null; + 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/"; @@ -55,6 +57,7 @@ public class MarketUploader implements TopLevelWindowListener, GUIInitializedLis private boolean uploadToYarrg; private boolean uploadToPCTB; + private boolean showArbitrage; private String islandName = null; private String oceanName = null; @@ -78,6 +81,28 @@ public class MarketUploader implements TopLevelWindowListener, GUIInitializedLis } } }; + + private int parseQty(String str) { + if (str.equals(">1000")) { + return 1001; + } else { + return Integer.parseInt(str); + } + } + + private void progresslog(String s) { + long now = new Date().getTime(); + System.out.println("progress "+(now - startTime)+"ms "+s); + } + + 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 @@ -108,11 +133,7 @@ public class MarketUploader implements TopLevelWindowListener, GUIInitializedLis commodity = commodId.intValue(); price = Integer.parseInt(record.get(priceIndex)); String qty = record.get(priceIndex+1); - if(qty.equals(">1000")) { - quantity = 1001; - } else { - quantity = Integer.parseInt(record.get(priceIndex+1)); - } + quantity = parseQty(qty); shoppe = stallMap.get(record.get(1)).intValue(); } @@ -225,6 +246,7 @@ public class MarketUploader implements TopLevelWindowListener, GUIInitializedLis uploadToYarrg=prefs.getBoolean("uploadToYarrg", true); uploadToPCTB=prefs.getBoolean("uploadToPCTB", true); + showArbitrage=prefs.getBoolean("showArbitrage", true); EventQueueMonitor.addTopLevelWindowListener(this); if (EventQueueMonitor.isGUIInitialized()) { @@ -244,9 +266,10 @@ public class MarketUploader implements TopLevelWindowListener, GUIInitializedLis if (window.getAccessibleContext().getAccessibleName().equals("Puzzle Pirates")) frame.setVisible(true); return; } - frame = new JFrame("MarketUploader"); + frame = new JFrame("Jarrg Uploader"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - frame.getContentPane().setLayout(new GridLayout(2,1)); + GridLayout layout = new GridLayout(2,1); + frame.getContentPane().setLayout(layout); //frame.setPreferredSize(new Dimension(200, 60)); findMarket = new JButton("Upload Market Data"); @@ -255,7 +278,9 @@ public class MarketUploader implements TopLevelWindowListener, GUIInitializedLis findMarket.setEnabled(false); new Thread() { public void run() { + startTime = new Date().getTime(); resultSummary.setText(""); + arbitrageResult.setText(""); try { runPCTB(); } catch(Exception e) { @@ -279,6 +304,13 @@ public class MarketUploader implements TopLevelWindowListener, GUIInitializedLis resultSummary = new JLabel("ready"); frame.add(resultSummary); + arbitrageResult = new JLabel(""); + + if (showArbitrage) { + layout.setRows(layout.getRows() + 1); + frame.add(arbitrageResult); + } + frame.pack(); } @@ -368,6 +400,8 @@ public class MarketUploader implements TopLevelWindowListener, GUIInitializedLis * @exception Exception if an error we didn't expect occured */ private void runPCTB() throws Exception { + progresslog("starting"); + String yarrgts = ""; ProgressMonitor pm = new ProgressMonitor(frame,"Processing Market Data","Getting table data",0,100); pm.setMillisToDecideToPopup(0); @@ -375,7 +409,9 @@ public class MarketUploader implements TopLevelWindowListener, GUIInitializedLis boolean doneyarrg = false, donepctb = false; if (uploadToYarrg) { + progresslog("yarrg timestamp..."); yarrgts = getYarrgTimestamp(); + progresslog("yarrg timestamp done."); } AccessibleTable accesstable = findMarketTable(); @@ -392,13 +428,18 @@ public class MarketUploader implements TopLevelWindowListener, GUIInitializedLis return; } + progresslog("getisland..."); getIsland(); + progresslog("getocean..."); getOcean(); + progresslog("getocean done"); if (latch != null) { latch.await(2, java.util.concurrent.TimeUnit.SECONDS); } + progresslog("table check..."); + String headings_expected[] = new String[] { "Commodity", "Trading outlet", "Buy price", "Will buy", "Sell price", "Will sell" }; ArrayList> headers = getData(accesstable.getAccessibleColumnHeader()); @@ -421,10 +462,19 @@ public class MarketUploader implements TopLevelWindowListener, GUIInitializedLis } } + progresslog("table read..."); + ArrayList> data = getData(accesstable); + if (showArbitrage) { + progresslog("arbitrage..."); + calculateArbitrage(data); + progresslog("arbitrage done."); + } + if (uploadToYarrg && yarrgts != null) { - pm.setNote("Yarrg: Preparing data"); + progresslog("yarrg prepare..."); + progressNote(pm, "Yarrg: Preparing data"); pm.setProgress(10); StringBuilder yarrgsb = new StringBuilder(); @@ -444,17 +494,20 @@ public class MarketUploader implements TopLevelWindowListener, GUIInitializedLis yarrgdata = yarrgsb.toString(); - pm.setNote("Yarrg: Uploading"); + progressNote(pm, "Yarrg: Uploading"); + progresslog("yarrg upload..."); if (islandName != null) { doneyarrg = runYarrg(yarrgts, oceanName, islandName, yarrgdata); } else { System.out.println("Couldn't upload to Yarrg - no island name found"); } + progresslog("yarrg done."); } if (uploadToPCTB) { - pm.setNote("PCTB: Getting stall names"); + progresslog("pctb prepare..."); + progressNote(pm, "PCTB: Getting stall names"); pm.setProgress(20); if(pm.isCanceled()) { return; @@ -463,7 +516,7 @@ public class MarketUploader implements TopLevelWindowListener, GUIInitializedLis TreeSet sells = new TreeSet(); LinkedHashMap stallMap = getStallMap(data); pm.setProgress(40); - pm.setNote("PCTB: Sorting offers"); + progressNote(pm, "PCTB: Sorting offers"); if(pm.isCanceled()) { return; } @@ -480,7 +533,7 @@ public class MarketUploader implements TopLevelWindowListener, GUIInitializedLis ByteArrayOutputStream outStream = new ByteArrayOutputStream(); pm.setProgress(60); - pm.setNote("PCTB: Sending data"); + progressNote(pm, "PCTB: Sending data"); if(pm.isCanceled()) { return; } @@ -492,14 +545,18 @@ public class MarketUploader implements TopLevelWindowListener, GUIInitializedLis dos.writeBytes(getAbbrevStallList(stallMap)); writeBuySellOffers(buys,sells,offerCount,out); out.finish(); + progresslog("pctb send..."); InputStream in = sendInitialData(new ByteArrayInputStream(outStream.toByteArray())); + progresslog("pctb sent."); if (in == null) return; pm.setProgress(80); if(pm.isCanceled()) { return; } - pm.setNote("PCTB: Waiting ..."); + progressNote(pm, "PCTB: Waiting ..."); + progresslog("pctb finish..."); donepctb = finishUpload(in); + progresslog("pctb done."); } pm.setProgress(100); @@ -511,6 +568,7 @@ public class MarketUploader implements TopLevelWindowListener, GUIInitializedLis } else { resultSummary.setText("uploaded nowhere!"); } + progresslog("done."); } /** @@ -975,5 +1033,85 @@ public class MarketUploader implements TopLevelWindowListener, GUIInitializedLis } return true; } + + private int calculateArbitrageCommodity(ArrayList> arb_bs) { + //System.out.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]; + //System.out.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); + } + //System.out.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") + 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); + //System.out.println("ROW "+row.toString()); + if (lastcommod == null || !thiscommod.equals(lastcommod)) { + if (lastcommod != null) + arbitrage += calculateArbitrageCommodity(arb_bs); + //System.out.println("ROW rdy"); + arb_bs = new ArrayList>(2); + arb_bs.add(0, new TreeSet(compar)); + arb_bs.add(1, new TreeSet(compar)); + //System.out.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]; + //System.out.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"); + } + } }