liquid_feedback_core
changeset 399:db863178d98b
Algorithm to write "issue_order"."order_in_open_states"
author | jbe |
---|---|
date | Fri Oct 11 20:50:16 2013 +0200 (2013-10-11) |
parents | 806561cce3b1 |
children | 782eb17c7ad9 |
files | lf_update_issue_order.c |
line diff
1.1 --- a/lf_update_issue_order.c Fri Oct 11 20:07:41 2013 +0200 1.2 +++ b/lf_update_issue_order.c Fri Oct 11 20:50:16 2013 +0200 1.3 @@ -88,6 +88,13 @@ 1.4 struct candidate **candidates; 1.5 }; 1.6 1.7 +// open issue to be assigned an "order_in_open_states": 1.8 +struct open_issue { 1.9 + char *issue_id; 1.10 + int minimum_position; 1.11 + int position; 1.12 +}; 1.13 + 1.14 // determine candidate, which is assigned the next seat (starting with the worst rank): 1.15 static struct candidate *loser(int round_number, struct ballot *ballots, int ballot_count) { 1.16 int i, j; // index variables for loops 1.17 @@ -173,7 +180,28 @@ 1.18 abort(); 1.19 } 1.20 1.21 -// write results to database: 1.22 +// calculate "order_in_open_states": 1.23 +static void calculate_order_in_open_states(struct open_issue *open_issues, int open_issue_count) { 1.24 + int i, j, fallback_j = 0, fallback_minimum_position; 1.25 + for (i=1; i<=open_issue_count; i++) { 1.26 + fallback_minimum_position = -1; 1.27 + for (j=0; j<open_issue_count; j++) { 1.28 + if (open_issues[j].position) continue; 1.29 + if (open_issues[j].minimum_position <= i) break; 1.30 + if ( 1.31 + fallback_minimum_position < 0 || 1.32 + open_issues[j].minimum_position < fallback_minimum_position 1.33 + ) { 1.34 + fallback_j = j; 1.35 + fallback_minimum_position = open_issues[j].minimum_position; 1.36 + } 1.37 + } 1.38 + if (j==open_issue_count) j = fallback_j; 1.39 + open_issues[j].position = i; 1.40 + } 1.41 +} 1.42 + 1.43 +// write results to database (calls calculate_open_issue_order): 1.44 static int write_ranks(PGconn *db, char *escaped_area_id) { 1.45 PGresult *res; 1.46 char *cmd; 1.47 @@ -204,7 +232,7 @@ 1.48 fprintf(stderr, "Could not escape literal in memory.\n"); 1.49 abort(); 1.50 } 1.51 - if (asprintf(&cmd, "INSERT INTO \"issue_order\" (\"id\", \"order_in_admission_state\") VALUES (%i, %s)", candidates[i].seat, escaped_issue_id) < 0) { 1.52 + if (asprintf(&cmd, "INSERT INTO \"issue_order\" (\"id\", \"order_in_admission_state\") VALUES (%s, %i)", escaped_issue_id, candidates[i].seat) < 0) { 1.53 fprintf(stderr, "Could not prepare query string in memory.\n"); 1.54 abort(); 1.55 } 1.56 @@ -227,6 +255,85 @@ 1.57 if (res) PQclear(res); 1.58 return 1; 1.59 } 1.60 + if (asprintf(&cmd, "SELECT \"issue_id\", \"minimum_position\" FROM \"open_issues_ordered_with_minimum_position\" WHERE \"area_id\" = %s", escaped_area_id) < 0) { 1.61 + fprintf(stderr, "Could not prepare query string in memory.\n"); 1.62 + abort(); 1.63 + } 1.64 + res = PQexec(db, cmd); 1.65 + free(cmd); 1.66 + if (!res) { 1.67 + fprintf(stderr, "Error in pqlib while sending SQL command selecting ordered issues with minimum position.\n"); 1.68 + res = PQexec(db, "ROLLBACK"); 1.69 + if (res) PQclear(res); 1.70 + return 1; 1.71 + } else if (PQresultStatus(res) != PGRES_TUPLES_OK) { 1.72 + fprintf(stderr, "Error while executing SQL command selecting ordered issues with minimum position:\n%s", PQresultErrorMessage(res)); 1.73 + PQclear(res); 1.74 + res = PQexec(db, "ROLLBACK"); 1.75 + if (res) PQclear(res); 1.76 + return 1; 1.77 + } else if (PQnfields(res) < 2) { 1.78 + fprintf(stderr, "Too few columns returned by SQL command selecting ordered issues with minimum position.\n"); 1.79 + PQclear(res); 1.80 + res = PQexec(db, "ROLLBACK"); 1.81 + if (res) PQclear(res); 1.82 + return 1; 1.83 + } else { 1.84 + int open_issue_count; 1.85 + struct open_issue *open_issues; 1.86 + open_issue_count = PQntuples(res); 1.87 + open_issues = calloc(open_issue_count, sizeof(struct open_issue)); 1.88 + for (i=0; i<open_issue_count; i++) { 1.89 + open_issues[i].issue_id = PQgetvalue(res, i, 0); 1.90 + if (PQgetisnull(res, i, 1)) { 1.91 + open_issues[i].minimum_position = 0; 1.92 + } else { 1.93 + open_issues[i].minimum_position = (int)strtol(PQgetvalue(res, i, 1), (char **)NULL, 10); 1.94 + if (open_issues[i].minimum_position < 1) { 1.95 + fprintf(stderr, "Unexpected minimum position value.\n"); 1.96 + PQclear(res); 1.97 + free(open_issues); 1.98 + res = PQexec(db, "ROLLBACK"); 1.99 + if (res) PQclear(res); 1.100 + return 1; 1.101 + } 1.102 + } 1.103 + } 1.104 + PQclear(res); 1.105 + calculate_order_in_open_states(open_issues, open_issue_count); 1.106 + for (i=0; i<open_issue_count; i++) { 1.107 + char *escaped_issue_id; 1.108 + escaped_issue_id = escapeLiteral(db, open_issues[i].issue_id, strlen(open_issues[i].issue_id)); 1.109 + if (!escaped_issue_id) { 1.110 + fprintf(stderr, "Could not escape literal in memory.\n"); 1.111 + abort(); 1.112 + } 1.113 + if (asprintf(&cmd, "UPDATE \"issue_order\" SET \"order_in_open_states\" = %i WHERE \"id\" = %s)", open_issues[i].position, escaped_issue_id) < 0) { 1.114 + fprintf(stderr, "Could not prepare query string in memory.\n"); 1.115 + abort(); 1.116 + } 1.117 + freemem(escaped_issue_id); 1.118 + res = PQexec(db, cmd); 1.119 + free(cmd); 1.120 + if (!res) { 1.121 + fprintf(stderr, "Error in pqlib while sending SQL command to update issue order.\n"); 1.122 + } else if ( 1.123 + PQresultStatus(res) != PGRES_COMMAND_OK && 1.124 + PQresultStatus(res) != PGRES_TUPLES_OK 1.125 + ) { 1.126 + fprintf(stderr, "Error while executing SQL command to update issue order:\n%s", PQresultErrorMessage(res)); 1.127 + PQclear(res); 1.128 + } else { 1.129 + PQclear(res); 1.130 + continue; 1.131 + } 1.132 + free(open_issues); 1.133 + res = PQexec(db, "ROLLBACK"); 1.134 + if (res) PQclear(res); 1.135 + return 1; 1.136 + } 1.137 + free(open_issues); 1.138 + } 1.139 res = PQexec(db, "COMMIT"); 1.140 if (!res) { 1.141 fprintf(stderr, "Error in pqlib while sending SQL command to commit transaction.\n"); 1.142 @@ -240,8 +347,8 @@ 1.143 return 1; 1.144 } else { 1.145 PQclear(res); 1.146 - return 0; 1.147 } 1.148 + return 0; 1.149 } 1.150 1.151 // calculate ordering of issues in admission state for an area and call write_ranks() to write it to database: