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:

Impressum / About Us