liquid_feedback_core
diff lf_update_issue_order.c @ 410:d301dc24b25c
Proportional Runoff for issues both based on single areas and single units
author | jbe |
---|---|
date | Mon Oct 14 19:36:33 2013 +0200 (2013-10-14) |
parents | 5f24058af0b8 |
children | 82387194519b |
line diff
1.1 --- a/lf_update_issue_order.c Mon Oct 14 00:58:38 2013 +0200 1.2 +++ b/lf_update_issue_order.c Mon Oct 14 19:36:33 2013 +0200 1.3 @@ -174,16 +174,11 @@ 1.4 } 1.5 1.6 // write results to database: 1.7 -static int write_ranks(PGconn *db, char *escaped_area_id) { 1.8 +static int write_ranks(PGconn *db, char *escaped_area_or_unit_id, char *mode) { 1.9 PGresult *res; 1.10 char *cmd; 1.11 int i; 1.12 - if (asprintf(&cmd, "BEGIN; DELETE FROM \"issue_order\" USING \"issue\" WHERE \"issue_order\".\"id\" = \"issue\".\"id\" AND \"issue\".\"area_id\" = %s", escaped_area_id) < 0) { 1.13 - fprintf(stderr, "Could not prepare query string in memory.\n"); 1.14 - abort(); 1.15 - } 1.16 - res = PQexec(db, cmd); 1.17 - free(cmd); 1.18 + res = PQexec(db, "BEGIN"); 1.19 if (!res) { 1.20 fprintf(stderr, "Error in pqlib while sending SQL command to initiate issue order update.\n"); 1.21 return 1; 1.22 @@ -204,7 +199,7 @@ 1.23 fprintf(stderr, "Could not escape literal in memory.\n"); 1.24 abort(); 1.25 } 1.26 - if (asprintf(&cmd, "INSERT INTO \"issue_order\" (\"id\", \"order_in_admission_state\", \"max_supporter_count\") SELECT %s, %i, max(\"supporter_count\") FROM \"initiative\" WHERE \"issue_id\" = %s", escaped_issue_id, candidates[i].seat, escaped_issue_id) < 0) { 1.27 + if (asprintf(&cmd, "UPDATE \"issue_order_in_admission_state\" SET \"order_in_%s\" = %i WHERE \"id\" = %s", mode, candidates[i].seat, escaped_issue_id) < 0) { 1.28 fprintf(stderr, "Could not prepare query string in memory.\n"); 1.29 abort(); 1.30 } 1.31 @@ -212,12 +207,12 @@ 1.32 res = PQexec(db, cmd); 1.33 free(cmd); 1.34 if (!res) { 1.35 - fprintf(stderr, "Error in pqlib while sending SQL command to insert issue order.\n"); 1.36 + fprintf(stderr, "Error in pqlib while sending SQL command to update issue order.\n"); 1.37 } else if ( 1.38 PQresultStatus(res) != PGRES_COMMAND_OK && 1.39 PQresultStatus(res) != PGRES_TUPLES_OK 1.40 ) { 1.41 - fprintf(stderr, "Error while executing SQL command to insert issue order:\n%s", PQresultErrorMessage(res)); 1.42 + fprintf(stderr, "Error while executing SQL command to update issue order:\n%s", PQresultErrorMessage(res)); 1.43 PQclear(res); 1.44 } else { 1.45 PQclear(res); 1.46 @@ -245,7 +240,7 @@ 1.47 } 1.48 1.49 // calculate ordering of issues in admission state for an area and call write_ranks() to write it to database: 1.50 -static int process_area(PGconn *db, PGresult *res, char *escaped_area_id) { 1.51 +static int process_area_or_unit(PGconn *db, PGresult *res, char *escaped_area_or_unit_id, char *mode) { 1.52 int err; // variable to store an error condition (0 = success) 1.53 int ballot_count = 1; // number of ballots, must be initiatized to 1, due to loop below 1.54 struct ballot *ballots; // data structure containing the ballots 1.55 @@ -265,7 +260,7 @@ 1.56 if (!tuple_count) { 1.57 // write results to database: 1.58 if (logging) printf("No supporters for any issue. Writing ranks to database.\n"); 1.59 - err = write_ranks(db, escaped_area_id); 1.60 + err = write_ranks(db, escaped_area_or_unit_id, mode); 1.61 if (logging) printf("Done.\n"); 1.62 return 0; 1.63 } 1.64 @@ -377,7 +372,7 @@ 1.65 1.66 // write results to database: 1.67 if (logging) printf("Writing ranks to database.\n"); 1.68 - err = write_ranks(db, escaped_area_id); 1.69 + err = write_ranks(db, escaped_area_or_unit_id, mode); 1.70 if (logging) printf("Done.\n"); 1.71 1.72 // free candidates[] array: 1.73 @@ -445,6 +440,23 @@ 1.74 return 1; 1.75 } 1.76 1.77 + // create missing "issue_order_in_admission_state" entries for issues 1.78 + res = PQexec(db, "INSERT INTO \"issue_order_in_admission_state\" (\"id\") SELECT \"issue\".\"id\" FROM \"issue\" NATURAL LEFT JOIN \"issue_order_in_admission_state\" WHERE \"issue\".\"state\" = 'admission'::\"issue_state\" AND \"issue_order_in_admission_state\".\"id\" ISNULL"); 1.79 + if (!res) { 1.80 + fprintf(stderr, "Error in pqlib while sending SQL command creating new issue order entries.\n"); 1.81 + err = 1; 1.82 + } else if ( 1.83 + PQresultStatus(res) != PGRES_COMMAND_OK && 1.84 + PQresultStatus(res) != PGRES_TUPLES_OK 1.85 + ) { 1.86 + fprintf(stderr, "Error while executing SQL command creating new issue order entries:\n%s", PQresultErrorMessage(res)); 1.87 + err = 1; 1.88 + PQclear(res); 1.89 + } else { 1.90 + if (logging) printf("Created %s new issue order entries.\n", PQcmdTuples(res)); 1.91 + PQclear(res); 1.92 + } 1.93 + 1.94 // go through areas: 1.95 res = PQexec(db, "SELECT \"id\" FROM \"area\""); 1.96 if (!res) { 1.97 @@ -490,7 +502,7 @@ 1.98 err = 1; 1.99 PQclear(res2); 1.100 } else { 1.101 - if (process_area(db, res2, escaped_area_id)) err = 1; 1.102 + if (process_area_or_unit(db, res2, escaped_area_id, "area")) err = 1; 1.103 PQclear(res2); 1.104 } 1.105 freemem(escaped_area_id); 1.106 @@ -498,8 +510,61 @@ 1.107 PQclear(res); 1.108 } 1.109 1.110 + // go through units: 1.111 + res = PQexec(db, "SELECT \"id\" FROM \"unit\""); 1.112 + if (!res) { 1.113 + fprintf(stderr, "Error in pqlib while sending SQL command selecting units to process.\n"); 1.114 + err = 1; 1.115 + } else if (PQresultStatus(res) != PGRES_TUPLES_OK) { 1.116 + fprintf(stderr, "Error while executing SQL command selecting units to process:\n%s", PQresultErrorMessage(res)); 1.117 + err = 1; 1.118 + PQclear(res); 1.119 + } else if (PQnfields(res) < 1) { 1.120 + fprintf(stderr, "Too few columns returned by SQL command selecting units to process.\n"); 1.121 + err = 1; 1.122 + PQclear(res); 1.123 + } else { 1.124 + count = PQntuples(res); 1.125 + if (logging) printf("Number of units to process: %i\n", count); 1.126 + for (i=0; i<count; i++) { 1.127 + char *unit_id, *escaped_unit_id; 1.128 + char *cmd; 1.129 + PGresult *res2; 1.130 + unit_id = PQgetvalue(res, i, 0); 1.131 + if (logging) printf("Processing unit #%s:\n", unit_id); 1.132 + escaped_unit_id = escapeLiteral(db, unit_id, strlen(unit_id)); 1.133 + if (!escaped_unit_id) { 1.134 + fprintf(stderr, "Could not escape literal in memory.\n"); 1.135 + abort(); 1.136 + } 1.137 + if (asprintf(&cmd, "SELECT \"member_id\", \"weight\", \"issue_id\" FROM \"issue_supporter_in_admission_state\" WHERE \"unit_id\" = %s ORDER BY \"member_id\"", escaped_unit_id) < 0) { 1.138 + fprintf(stderr, "Could not prepare query string in memory.\n"); 1.139 + abort(); 1.140 + } 1.141 + res2 = PQexec(db, cmd); 1.142 + free(cmd); 1.143 + if (!res2) { 1.144 + fprintf(stderr, "Error in pqlib while sending SQL command selecting issue supporter in admission state.\n"); 1.145 + err = 1; 1.146 + } else if (PQresultStatus(res2) != PGRES_TUPLES_OK) { 1.147 + fprintf(stderr, "Error while executing SQL command selecting issue supporter in admission state:\n%s", PQresultErrorMessage(res)); 1.148 + err = 1; 1.149 + PQclear(res2); 1.150 + } else if (PQnfields(res2) < 3) { 1.151 + fprintf(stderr, "Too few columns returned by SQL command selecting issue supporter in admission state.\n"); 1.152 + err = 1; 1.153 + PQclear(res2); 1.154 + } else { 1.155 + if (process_area_or_unit(db, res2, escaped_unit_id, "unit")) err = 1; 1.156 + PQclear(res2); 1.157 + } 1.158 + freemem(escaped_unit_id); 1.159 + } 1.160 + PQclear(res); 1.161 + } 1.162 + 1.163 // clean-up entries of deleted issues 1.164 - res = PQexec(db, "DELETE FROM \"issue_order\" USING \"issue_order\" AS \"issue_order2\" NATURAL LEFT JOIN \"issue\" WHERE \"issue_order\".\"id\" = \"issue_order2\".\"id\" AND \"issue\".\"id\" ISNULL"); 1.165 + res = PQexec(db, "DELETE FROM \"issue_order_in_admission_state\" USING \"issue_order_in_admission_state\" AS \"self\" NATURAL LEFT JOIN \"issue\" WHERE \"issue_order_in_admission_state\".\"id\" = \"self\".\"id\" AND (\"issue\".\"id\" ISNULL OR \"issue\".\"state\" != 'admission'::\"issue_state\")"); 1.166 if (!res) { 1.167 fprintf(stderr, "Error in pqlib while sending SQL command deleting ordering data of deleted issues.\n"); 1.168 err = 1;