liquid_feedback_core

changeset 356:4698b68e0942

Calculation of ranks in "lf_update_suggestion_order"
author jbe
date Sun Mar 17 09:28:39 2013 +0100 (2013-03-17)
parents accffcefeff7
children d420e7a5a75f
files lf_update_suggestion_order.c
line diff
     1.1 --- a/lf_update_suggestion_order.c	Sat Mar 16 18:29:55 2013 +0100
     1.2 +++ b/lf_update_suggestion_order.c	Sun Mar 17 09:28:39 2013 +0100
     1.3 @@ -31,6 +31,8 @@
     1.4  
     1.5  struct candidate {
     1.6    char *key;
     1.7 +  double score_per_step;
     1.8 +  int reaches_score;
     1.9    double score;
    1.10    int seat;
    1.11  };
    1.12 @@ -47,7 +49,6 @@
    1.13      struct candidate *candidate;
    1.14      candidate = candidates + (candidate_count++);
    1.15      candidate->key   = *candidate_key;
    1.16 -    candidate->score = 0.0;
    1.17      candidate->seat  = 0;
    1.18    }
    1.19  }
    1.20 @@ -58,7 +59,7 @@
    1.21    compare.key = candidate_key;
    1.22    candidate = bsearch(&compare, candidates, candidate_count, sizeof(struct candidate), (void *)compare_candidate);
    1.23    if (!candidate) {
    1.24 -    fprintf(stderr, "Candidate not found (should not happen)\n");
    1.25 +    fprintf(stderr, "Candidate not found (should not happen).\n");
    1.26      abort();
    1.27    }
    1.28    return candidate;
    1.29 @@ -74,10 +75,77 @@
    1.30    struct ballot_section sections[4];
    1.31  };
    1.32  
    1.33 +static struct candidate *loser(int round_number, struct ballot *ballots, int ballot_count) {
    1.34 +  int i, j, k;
    1.35 +  int remaining;
    1.36 +  for (i=0; i<candidate_count; i++) {
    1.37 +    candidates[i].score = 0.0;
    1.38 +  }
    1.39 +  remaining = candidate_count - round_number;
    1.40 +  while (1) {
    1.41 +    double scale;
    1.42 +    if (remaining <= 1) break;
    1.43 +    for (i=0; i<candidate_count; i++) {
    1.44 +      candidates[i].score_per_step = 0.0;
    1.45 +      candidates[i].reaches_score = 0;
    1.46 +    }
    1.47 +    for (i=0; i<ballot_count; i++) {
    1.48 +      for (j=0; j<4; j++) {
    1.49 +        int matches = 0;
    1.50 +        for (k=0; k<ballots[i].sections[j].count; k++) {
    1.51 +          struct candidate *candidate;
    1.52 +          candidate = ballots[i].sections[j].candidates[k];
    1.53 +          if (candidate->score < 1.0 && !candidate->seat) matches++;
    1.54 +        }
    1.55 +        if (matches) {
    1.56 +          double score_inc;
    1.57 +          score_inc = 1.0 / (double)matches;
    1.58 +          for (k=0; k<ballots[i].sections[j].count; k++) {
    1.59 +            struct candidate *candidate;
    1.60 +            candidate = ballots[i].sections[j].candidates[k];
    1.61 +            if (candidate->score < 1.0 && !candidate->seat) {
    1.62 +              candidate->score_per_step += score_inc;
    1.63 +            }
    1.64 +          }
    1.65 +          break;
    1.66 +        }
    1.67 +      }
    1.68 +    }
    1.69 +    scale = (double)candidate_count;
    1.70 +    for (i=0; i<candidate_count; i++) {
    1.71 +      double max_scale;
    1.72 +      if (candidates[i].score_per_step > 0.0) {
    1.73 +        max_scale = (1.0-candidates[i].score) / candidates[i].score_per_step;
    1.74 +        if (max_scale <= scale) {
    1.75 +          scale = max_scale;
    1.76 +          candidates[i].reaches_score = 1;
    1.77 +        }
    1.78 +      }
    1.79 +    }
    1.80 +    for (i=0; i<candidate_count; i++) {
    1.81 +      if (candidates[i].score_per_step > 0.0) {
    1.82 +        if (candidates[i].reaches_score) {
    1.83 +          candidates[i].score = 1.0;
    1.84 +          remaining--;
    1.85 +        } else {
    1.86 +          candidates[i].score += scale * candidates[i].score_per_step;
    1.87 +          if (candidates[i].score >= 1.0) remaining--;
    1.88 +        }
    1.89 +        if (remaining <= 1) break;
    1.90 +      }
    1.91 +    }
    1.92 +  }
    1.93 +  for (i=candidate_count-1; i>=0; i--) {
    1.94 +    if (candidates[i].score < 1.0 && !candidates[i].seat) return candidates+i;
    1.95 +  }
    1.96 +  fprintf(stderr, "No remaining candidate (should not happen).");
    1.97 +  abort();
    1.98 +}
    1.99 +
   1.100  static void process_initiative(PGresult *res) {
   1.101    int ballot_count = 0;
   1.102 +  struct ballot *ballots;
   1.103    int i;
   1.104 -  struct ballot *ballots;
   1.105    {
   1.106      void *candidate_tree = NULL;
   1.107      int tuple_count;
   1.108 @@ -94,7 +162,7 @@
   1.109          if (!candidate_tree || !tfind(suggestion_id, &candidate_tree, (void *)strcmp)) {
   1.110            candidate_count++;
   1.111            if (!tsearch(suggestion_id, &candidate_tree, (void *)strcmp)) {
   1.112 -            fprintf(stderr, "Insufficient memory\n");
   1.113 +            fprintf(stderr, "Insufficient memory while inserting into candidate tree.\n");
   1.114              abort();
   1.115            }
   1.116          }
   1.117 @@ -107,7 +175,7 @@
   1.118      printf("Candidate count: %i\n", candidate_count);
   1.119      candidates = malloc(candidate_count * sizeof(struct candidate));
   1.120      if (!candidates) {
   1.121 -      fprintf(stderr, "Insufficient memory\n");
   1.122 +      fprintf(stderr, "Insufficient memory while creating candidate list.\n");
   1.123        abort();
   1.124      }
   1.125      candidate_count = 0;
   1.126 @@ -116,7 +184,7 @@
   1.127      printf("Ballot count: %i\n", ballot_count);
   1.128      ballots = calloc(ballot_count, sizeof(struct ballot));
   1.129      if (!ballots) {
   1.130 -      fprintf(stderr, "Insufficient memory\n");
   1.131 +      fprintf(stderr, "Insufficient memory while creating ballot list.\n");
   1.132        abort();
   1.133      }
   1.134      ballot = ballots;
   1.135 @@ -127,12 +195,12 @@
   1.136        suggestion_id = PQgetvalue(res, i, COL_SUGGESTION_ID);
   1.137        weight = (int)strtol(PQgetvalue(res, i, COL_WEIGHT), (char **)NULL, 10);
   1.138        if (weight <= 0) {
   1.139 -        fprintf(stderr, "Unexpected weight value\n");
   1.140 +        fprintf(stderr, "Unexpected weight value.\n");
   1.141          abort();
   1.142        }
   1.143        preference = (int)strtol(PQgetvalue(res, i, COL_PREFERENCE), (char **)NULL, 10);
   1.144        if (preference < 1 || preference > 4) {
   1.145 -        fprintf(stderr, "Unexpected preference value\n");
   1.146 +        fprintf(stderr, "Unexpected preference value.\n");
   1.147          abort();
   1.148        }
   1.149        preference--;
   1.150 @@ -147,7 +215,7 @@
   1.151          if (ballots[i].sections[j].count) {
   1.152            ballots[i].sections[j].candidates = malloc(ballots[i].sections[j].count * sizeof(struct candidate *));
   1.153            if (!ballots[i].sections[j].candidates) {
   1.154 -            fprintf(stderr, "Insufficient memory\n");
   1.155 +            fprintf(stderr, "Insufficient memory while creating ballot section.\n");
   1.156              abort();
   1.157            }
   1.158          }
   1.159 @@ -161,10 +229,6 @@
   1.160          member_id = PQgetvalue(res, i, COL_MEMBER_ID);
   1.161          suggestion_id = PQgetvalue(res, i, COL_SUGGESTION_ID);
   1.162          preference = (int)strtol(PQgetvalue(res, i, COL_PREFERENCE), (char **)NULL, 10);
   1.163 -        if (preference < 1 || preference > 4) {
   1.164 -          fprintf(stderr, "Unexpected preference value\n");
   1.165 -          abort();
   1.166 -        }
   1.167          preference--;
   1.168          ballot->sections[preference].candidates[candidates_in_sections[preference]++] = candidate_by_key(suggestion_id);
   1.169        }
   1.170 @@ -179,6 +243,11 @@
   1.171      }
   1.172    }
   1.173  
   1.174 +  for (i=0; i<candidate_count; i++) {
   1.175 +    struct candidate *candidate = loser(i, ballots, ballot_count);
   1.176 +    candidate->seat = candidate_count - i;
   1.177 +  }
   1.178 +
   1.179    free(candidates);
   1.180    for (i=0; i<ballot_count; i++) {
   1.181      int j;
   1.182 @@ -273,6 +342,10 @@
   1.183          fprintf(stderr, "Error while executing SQL command selecting open issues:\n%s", PQresultErrorMessage(res));
   1.184          err = 1;
   1.185          PQclear(res2);
   1.186 +      } else if (PQnfields(res2) < 4) {
   1.187 +        fprintf(stderr, "Too few columns returned by SQL command selecting open issues.\n");
   1.188 +        err = 1;
   1.189 +        PQclear(res2);
   1.190        } else {
   1.191          if (PQntuples(res2) == 0) {
   1.192            printf("Nothing to do.\n");

Impressum / About Us