+ } /* for (d) */
+ next_s:;
+ } /* for (s) */
+
+ double profit= 0;
+
+ if (lpx_get_num_cols(lp)) {
+ ctr_subroutes_nonempty++;
+
+ if (DEBUGP(lp))
+ lpx_write_cpxlp(lp, (char*)DEBUG_DEV);
+
+ int ipr= lpx_simplex(lp);
+ assert(ipr==LPX_E_OK);
+
+ if (DEBUGP(lp))
+ lpx_print_sol(lp, (char*)DEBUG_DEV);
+
+ int lpst= lpx_get_status(lp);
+ assert(lpst == LPX_OPT);
+ profit= lpx_get_obj_val(lp);
+ }
+
+ lpx_delete_prob(lp);
+ lp= 0;
+
+ debugf(" %s %f\n",
+ exclude_arbitrage ? "base value" : "route value",
+ profit);
+ return profit;
+}
+
+#define TRADE_FROM \
+ " FROM sell, buy\n" \
+ " WHERE sell.commodid=buy.commodid AND sell.price < buy.price\n"
+
+static void read_trades(void) {
+ /* We would like to use DISTINCT but sqlite3 is too stupid
+ * to notice that it could use the index to do the DISTINCT
+ * which makes it rather slow. */
+ sqlite3_stmt *ss_trades;
+
+#define TRADE_COLS \
+ "sell.commodid, sell.islandid, sell.price, buy.islandid, buy.price"
+ SQL_PREPARE(ss_trades,
+ " SELECT " TRADE_COLS "\n"
+ TRADE_FROM
+ " ORDER BY " TRADE_COLS);
+
+ SQL_DISTINCT_DECL(cols,5);
+ while (SQL_DISTINCT_STEP(ss_trades,cols,5)) {
+ ctr_trades_loaded++;
+ IslandPair *ip= ipair_get_create(cols[1], cols[3]);
+ TradesBlock *block= ip->trades;
+ if (!block || ip->trades->ntrades >= TRADES_PER_BLOCK) {
+ NEW(block);
+ block->next= ip->trades;
+ ip->trades= block;
+ block->ntrades= 0;
+ }
+ Trade *trade= &block->t[block->ntrades];
+ trade->commodid= cols[0];
+ trade->src_price= cols[2];
+ trade->dst_price= cols[4];
+ block->ntrades++;
+ }
+ sqlite3_finalize(ss_trades);
+}
+
+static void read_islandtradeends(const char *bs, int srcdstoff) {
+
+#define TRADEEND_KEYCOLS "%s.commodid, %s.islandid, %s.stallid"
+ char *stmt= masprintf(" SELECT " TRADEEND_KEYCOLS ", %s.price, %s.qty\n"
+ TRADE_FROM
+ " ORDER BY " TRADEEND_KEYCOLS,
+ bs,bs,bs,bs,bs, bs,bs,bs);
+ char *stmt_id= masprintf("qtys (%s)",bs);
+ sqlite3_stmt *ss= sql_prepare(stmt, stmt_id);
+ free(stmt); free(stmt_id);
+
+ SQL_DISTINCT_DECL(cols,5);
+ while (SQL_DISTINCT_STEP(ss,cols,3)) {
+ ctr_quantities_loaded++;
+ IslandTradeEnd *search;
+
+ int commodid= cols[0];
+ int islandid= cols[1];
+ int price= cols[3];
+ int qty= cols[4];
+
+ IslandTradeEnd **trades= (void*)((char*)&itradeends[islandid] + srcdstoff);
+
+ for (search= *trades; search; search=search->next)
+ if (search->commodid==commodid && search->price==price)
+ goto found;
+ /* not found, add new end */
+
+ NEW(search);
+ search->commodid= commodid;
+ search->price= price;
+ search->next= *trades;
+ search->generation= 0;
+ search->qty= 0;
+ *trades= search;
+
+ found:
+ search->qty += qty;