CONVERT_OBJS= convert.o ocr.o pages.o structure.o rgbimage.o resolve.o
COMMON_OBJS= common.o
-ROUTESEARCH_OBJS= rsvalue.o rsmain.o rssetup.o
+ROUTESEARCH_OBJS= rsvalue.o rsmain.o rssql.o
yarrg: $(CONVERT_OBJS) $(COMMON_OBJS) -lnetpbm -lXtst -lX11 -lpcre -lm
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
extern unsigned debug_flags;
void debug_flush(void);
-#define debug stderr
+#ifndef debug
+# define debug stderr
+#endif
#define FMT(f,a) __attribute__((format(printf,f,a)))
#define SCANFMT(f,a) __attribute__((format(scanf,f,a)))
#define DEBUG_FLAG_LIST \
DF(sql) \
- DF(value)
+ DF(sql2) \
+ DF(value) \
+ DF(lp)
+#define debug stdout
+
+#include "common.h"
-#define SQL_MUST( call ) ({ \
+#define SQL_MUST( call ) ({ \
/* `call' is an expression returning result, using const char *sqe; \
* chk1 and chk2 are blocks using sqe and int sqr; */ \
const char *sql_must_call_string= #call; \
int sqr; \
- if (DEBUGP(sql)) fprintf(stderr,"SQL %s", sql_must_call_string); \
+ if (DEBUGP(sql2)) fprintf(stderr,"SQL %s", sql_must_call_string); \
sqr= (call); \
- if (DEBUGP(sql)) fprintf(stderr," = %d\n", sqr); \
- if (sqr) fatal("SQL call failed code %d: %s: %s", \
- sqr, sqlite3_errmsg(db), sql_must_call_string); \
- })
+ if (DEBUGP(sql2)) fprintf(stderr," = %d\n", sqr); \
+ if (sqr) sql_fatal("(unknown)", sqr, sql_must_call_string); \
+ }) \
+
+void sql_fatal(const char *stmt_what, int sqr, const char *act_what) NORET;
#define SQL_STEP(ssh) (sql_step_wrap((ssh), #ssh, __FILE__, __LINE__))
int sql_step_wrap(sqlite3_stmt *ssh, const char *ssh_string,
int sql_single_int(const char *stmt);
-#define MAX_ROUTELEN 20
+#define SQL_PREPARE(ss,stmt) ((ss)= sql_prepare((stmt),#ss))
+sqlite3_stmt *sql_prepare(const char *stmt, const char *what);
-#include "common.h"
+#define SQL_BIND(ss,index,value) (sql_bind((ss),(index),(value),#ss,#value))
+void sql_bind(sqlite3_stmt *ss, int index, int value,
+ const char *ss_what, const char *val_what);
+
+#define MAX_ROUTELEN 20
extern sqlite3 *db;
void setup(void);
-void value_route(int nislands, const int *islands);
+double value_route(int nislands, const int *islands);
void setup_value(void);
void setup_commods(void);
int main(int argc, const char **argv) {
int ia[argc], ni=0;
- debug_flags= ~0UL;
+ debug_flags= ~( dbg_sql2 );
setup();
max_mass= atof(*++argv);
while ((arg= *++argv)) {
ia[ni++]= atoi(arg);
}
- value_route(ni, ia);
+ double val= value_route(ni, ia);
+ printf("route value is %g\n", val);
return 0;
}
sqlite3 *db;
sqlite3_stmt *ss_ipair;
+DEBUG_DEFINE_DEBUGF(sql);
+
static int busy_handler(void *u, int previous) {
- if (DEBUGP(sql)) fprintf(stderr,"[[DB BUSY %d]]",previous);
+ debugf("[[DB BUSY %d]]",previous);
sysassert(! usleep(5000) );
return 1;
}
SQL_MUST( sqlite3_open("OCEAN-Midnight.db", &db) );
SQL_MUST( sqlite3_busy_handler(db, busy_handler, 0) );
- SQL_MUST( sqlite3_prepare(db, "BEGIN", -1, &sst, 0) );
+ sst= sql_prepare("BEGIN","(begin)");
assert( !SQL_STEP(sst) );
sqlite3_finalize(sst);
int sql_single_int(const char *stmt) {
sqlite3_stmt *sst;
- SQL_MUST( sqlite3_prepare(db, stmt, -1,&sst,0) );
+ sst= sql_prepare(stmt,"(single int)");
assert( SQL_STEP(sst) );
int rv= sqlite3_column_int(sst,0);
sqlite3_finalize(sst);
return rv;
}
+void sql_fatal(const char *stmt_what, int sqr, const char *act_what) {
+ fatal("SQL call failed, stmt %s code %d: %s: %s",
+ stmt_what, sqr, sqlite3_errmsg(db), act_what);
+}
+
+void sql_bind(sqlite3_stmt *ss, int index, int value,
+ const char *ss_what, const char *val_what) {
+ debugf("SQL BIND %s #%d = %d = %s\n", ss_what, index, value, val_what);
+ int sqr= sqlite3_bind_int(ss, index, value);
+ if (sqr) sql_fatal(ss_what, sqr,
+ masprintf("bind #%d (%s)", index, val_what));
+}
+
+sqlite3_stmt *sql_prepare(const char *stmt, const char *what) {
+ sqlite3_stmt *ssr;
+ debugf("SQL PREPARE %s [[\n%s\n]]\n", what, stmt);
+ SQL_MUST( sqlite3_prepare(db, stmt, -1, &ssr, 0) );
+ return ssr;
+}
+
int sql_step_wrap(sqlite3_stmt *ssh, const char *ssh_string,
const char *file, int line) {
for (;;) {
sqr= sqlite3_step((ssh));
switch (sqr) {
case SQLITE_DONE:
- if (DEBUGP(sql))
- fprintf(stderr,"SQL %s DONE\n",ssh_string);
+ debugf("SQL %s DONE\n",ssh_string);
return 0;
case SQLITE_ROW:
if (DEBUGP(sql)) {
int i;
- fprintf(stderr,"SQL %s R",ssh_string);
+ fprintf(debug,"SQL %s R",ssh_string);
for (i=0; i<sqlite3_column_count(ssh); i++) {
- fputc('\t',stderr);
+ fputc('\t',debug);
const char *txt= (const char*)sqlite3_column_text(ssh,i);
- fputs(txt ? txt : "<null>", stderr);
+ fputs(txt ? txt : "<null>", debug);
}
- fputs("\n",stderr);
+ fputs("\n",debug);
}
return 1;
default: fatal("SQL step failed at %s:%d: code %d: %s: %s",
#define MAX_LEGS (MAX_ROUTELEN-1)
typedef struct {
- int commodid, src_price, src_qty, dst_price, dst_qty;
+ int commodid, src_price, dst_price;
} Trade;
#define TRADES_PER_BLOCK 10
search->next= *trades;
search->generation= 0;
- SQL_MUST( sqlite3_bind_int(ss_ite, 1, islandid) );
- SQL_MUST( sqlite3_bind_int(ss_ite, 2, t->commodid) );
- SQL_MUST( sqlite3_bind_int(ss_ite, 3, price) );
+ SQL_BIND(ss_ite, 1, islandid);
+ SQL_BIND(ss_ite, 2, t->commodid);
+ SQL_BIND(ss_ite, 3, price);
assert(SQL_STEP(ss_ite));
search->qty= sqlite3_column_int(ss_ite, 0);
SQL_MUST( sqlite3_reset(ss_ite) );
lpx_set_row_bnds(lp, search->rownum, LPX_UP, 0, search->qty);
if (DEBUGP(value)) {
- char *name= masprintf("%s_commod%d_price%d",srcdst,t->commodid,price);
+ char *name= masprintf("%s_c%d_%d",srcdst,t->commodid,price);
lpx_set_row_name(lp,search->rownum,name);
free(name);
}
inblock= 0;
}
int *irp, i;
- for (i=0, irp=&block->t[inblock].commodid; i<5; i++, irp++)
+ for (i=0, irp=&block->t[inblock].commodid; i<3; i++, irp++)
*irp= sqlite3_column_int(ss_ipair_trades, i);
ip->ntrades++;
inblock++;
return ip;
}
-void value_route(int nislands, const int *islands) {
+double value_route(int nislands, const int *islands) {
int s,d;
/* We need to construct the LP problem. GLPK talks
assert(!lp);
lp= lpx_create_prob();
lpx_set_obj_dir(lp, LPX_MAX);
+ lpx_set_int_parm(lp, LPX_K_MSGLEV, DEBUGP(lp) ? 3 : 1);
+
if (DEBUGP(value)) {
lpx_set_prob_name(lp,(char*)"value_route");
lpx_set_obj_name(lp,(char*)"profit");
lpx_set_mat_col(lp, col, nconstraint_rows,
constraint_rows, constraint_coeffs);
if (DEBUGP(value)) {
- char *name= masprintf("trade_commod%d_port%d_at%d_port%d_at%d",
+ char *name= masprintf("c%d_p%d_%d_p%d_%d",
t->commodid, s, t->src_price, d, t->dst_price);
lpx_set_col_name(lp, col, name);
free(name);
}
+
+ col++;
} /* while (tradestodo-- >0) */
/*----- that's done adding these trades to the LP problem -----*/
next_s:;
} /* for (s) */
+ if (DEBUGP(lp))
+ lpx_write_cpxlp(lp, (char*)"/dev/stdout");
+
+ int ipr= lpx_interior(lp);
+ assert(ipr==LPX_E_OK);
+
+ if (DEBUGP(lp))
+ lpx_print_ips(lp, (char*)"/dev/stdout");
+
+ assert(lpx_ipt_status(lp) == LPX_T_OPT);
+ double profit= lpx_ipt_obj_val(lp);
+
lpx_delete_prob(lp);
lp= 0;
+
+ return profit;
}
void setup_value(void) {
for (i=0; i<commodstablesz; i++)
commodstable[i].mass= commodstable[i].volu= -1;
- SQL_MUST( sqlite3_prepare(db,
- "SELECT commodid,unitmass,unitvolume FROM commods", -1,&sst,0) );
+ SQL_PREPARE(sst,
+ "SELECT commodid,unitmass,unitvolume FROM commods");
while (SQL_STEP(sst)) {
int id= sqlite3_column_int(sst,0);
assert(id>=0 && id<commodstablesz);
}
sqlite3_finalize(sst);
- SQL_MUST( sqlite3_prepare(db,
- " SELECT dist from dists where aiid=? and biid=?",
- -1, &ss_ipair_dist, 0) );
-
- SQL_MUST( sqlite3_prepare(db,
- "SELECT DISTINCT\n"
- " sell.commodid commodid,\n"
- " sell.price src_price,\n"
- " buy.price dst_price\n"
- " FROM sell JOIN buy\n"
- " ON sell.commodid = buy.commodid\n"
- " AND buy.price > sell.price\n"
- " WHERE sell.islandid=?\n"
- " AND buy.islandid=?",
- -1, &ss_ipair_trades, 0) );
-
-#define BS(bs) \
- SQL_MUST( sqlite3_prepare(db, \
- "SELECT\n" \
- " sum(qty)\n" \
- " FROM " #bs "\n" \
- " WHERE islandid=?\n" \
- " AND commodid=?\n" \
- " AND price=?", \
- -1, &ss_ite_##bs, 0) );
+ SQL_PREPARE(ss_ipair_dist,
+ " SELECT dist FROM dists\n"
+ " WHERE aiid=? and biid=?");
+
+ SQL_PREPARE(ss_ipair_trades,
+ "SELECT DISTINCT\n"
+ " sell.commodid commodid,\n"
+ " sell.price src_price,\n"
+ " buy.price dst_price\n"
+ " FROM sell JOIN buy\n"
+ " ON sell.commodid = buy.commodid\n"
+ " AND buy.price > sell.price\n"
+ " WHERE sell.islandid=?\n"
+ " AND buy.islandid=?");
+
+#define BS(bs) \
+ SQL_PREPARE(ss_ite_##bs, \
+ "SELECT\n" \
+ " sum(qty)\n" \
+ " FROM " #bs "\n" \
+ " WHERE islandid=?\n" \
+ " AND commodid=?\n" \
+ " AND price=?");
BS(buy)
BS(sell)
#undef BS