+typedef struct IslandTradeEnd {
+ struct IslandTradeEnd *next;
+ int commodid, price;
+ int qty;
+ unsigned long generation;
+ int rownum;
+} IslandTradeEnd, *IslandDirnTradeEnds;
+
+typedef struct {
+ int islandid;
+ IslandDirnTradeEnds collect, deliver;
+} IslandTradeEnds;
+
+static LPX *lp;
+static unsigned long generation;
+
+static int nconstraint_rows;
+static int constraint_rows[1+2+3*MAX_LEGS];
+static double constraint_coeffs[1+2+3*MAX_LEGS];
+ /* dummy0, src, dst, for_each_leg( [mass], [volume], [capital] ) */
+
+static void add_constraint(int row, double coefficient) {
+ nconstraint_rows++; /* glpk indices start from 1 !!! */
+ constraint_rows [nconstraint_rows]= row;
+ constraint_coeffs[nconstraint_rows]= coefficient;
+}
+
+static void avail_c(const Trade *t, IslandDirnTradeEnds *trades,
+ int price, const char *srcdst,
+ int islandid, sqlite3_stmt *ss_ite) {
+ /* find row number of trade availability constraint */
+ IslandTradeEnd *search;
+
+ for (search= *trades; search; search=search->next)
+ if (search->commodid==t->commodid && search->price==price)
+ goto found;
+ /* not found, add new row */
+
+ search= mmalloc(sizeof(*search));
+ search->commodid= t->commodid;
+ search->price= price;
+ search->next= *trades;
+ search->generation= 0;
+
+ 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) );
+
+ *trades= search;
+
+ found:;
+ if (search->generation != generation) {
+ search->rownum= lpx_add_rows(lp, 1);
+ lpx_set_row_bnds(lp, search->rownum, LPX_UP, 0, search->qty);
+
+ if (DEBUGP(value)) {
+ char *name= masprintf("%s_c%d_%d",srcdst,t->commodid,price);
+ lpx_set_row_name(lp,search->rownum,name);
+ free(name);
+ }
+ search->generation= generation;
+ }
+
+ add_constraint(search->rownum, 1.0);
+}
+
+static int setup_leg_constraints(double max_thing, int legs, const char *wh) {
+ int leg, startrow;
+ if (max_thing < 0 || !legs) return -1;
+ startrow= lpx_add_rows(lp, legs);
+ for (leg=0; leg<legs; leg++) {
+ int row= leg+startrow;
+ lpx_set_row_bnds(lp, row, LPX_UP, 0, max_thing);
+ if (DEBUGP(value)) {
+ char *name= masprintf("max_leg%d_%s",leg,wh);
+ lpx_set_row_name(lp,row,name);
+ free(name);
+ }
+ }
+ return startrow;
+}
+
+static void add_leg_c(int startrow, int leg, double value) {
+ if (startrow<=0) return;
+ assert(value > 0);
+ add_constraint(startrow+leg, value);
+}
+