Skip to content
Extraits de code Groupes Projets
Valider efb3dcdc rédigé par Nicolas Joyard's avatar Nicolas Joyard
Parcourir les fichiers

Change score calculation to exponential decay

parent bf3d5b31
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
[{
"model": "memopol_settings.setting",
"pk": "SCORE_DECAY_NUM",
"fields": {
"value": "0",
"comment": "Numerator for decay rate in score formula. Set to 0 for no decay, 1 otherwise. Score formula is base_score * exp( -(vote_age*DECAY_NUM/DECAY_DENOM)^(2*EXPONENT) )."
}
},
{
"model": "memopol_settings.setting",
"pk": "SCORE_DECAY_DENOM",
"fields": {
"value": "1",
"comment": "Denominator for decay rate in score formula. Must be nonzero. Set to higher value to delay the score decay. Score formula is base_score * exp( -(vote_age*DECAY_NUM/DECAY_DENOM)^(2*EXPONENT) )."
}
},{
"model": "memopol_settings.setting",
"pk": "SCORE_EXPONENT",
"fields": {
"value": "1",
"comment": "Exponent for score formula. Set to higher value for a steeper decay around the cutoff. Score formula is base_score * exp( -(vote_age*DECAY_NUM/DECAY_DENOM)^(2*EXPONENT) )."
}
},{
"model": "memopol_settings.setting",
"pk": "SCORE_DECIMALS",
"fields": {
"value": "0",
"comment": "Number of score decimals to display. Use 0 for integers."
}
}]
\ No newline at end of file
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os
from django.core import serializers
from django.db import migrations
fixture_dir = os.path.abspath(
os.path.join(
os.path.dirname(__file__),
'../fixtures'))
fixture_filename = 'score_settings.json'
def load_fixture(apps, schema_editor):
fixture_file = os.path.join(fixture_dir, fixture_filename)
fixture = open(fixture_file, 'rb')
objects = serializers.deserialize('json', fixture, ignorenonexistent=True)
for obj in objects:
obj.save()
fixture.close()
class Migration(migrations.Migration):
dependencies = [
('memopol_settings', '0001_initial'),
]
operations = [
migrations.RunPython(load_fixture),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('representatives_recommendations', '0005_representativescore'),
]
operations = [
migrations.RunSQL(
"""
DROP VIEW "representatives_recommendations_votescores" CASCADE;
"""
),
migrations.AlterField(
model_name='recommendation',
name='weight',
field=models.FloatField(default=0),
),
migrations.RunSQL(
"""
CREATE VIEW "representatives_recommendations_votescores"
AS SELECT
representatives_votes_vote.id,
representatives_votes_vote."position",
representatives_votes_vote.proposal_id,
representatives_votes_vote.representative_id,
ROUND(CAST(EXP(-((decay_num.value * EXTRACT(days FROM CURRENT_DATE - representatives_votes_proposal.datetime) / decay_denom.value) ^ (2 * exponent.value)))
* (CASE
WHEN representatives_votes_vote."position"::text = representatives_recommendations_recommendation.recommendation::text THEN representatives_recommendations_recommendation.weight
ELSE 0 - representatives_recommendations_recommendation.weight
END) AS NUMERIC), decimals.value) AS score
FROM representatives_votes_vote
JOIN (SELECT CAST(TO_NUMBER(value, '99999') AS FLOAT) AS value FROM memopol_settings_setting WHERE key = 'SCORE_DECAY_NUM') decay_num ON 1=1
JOIN (SELECT CAST(TO_NUMBER(value, '99999') AS FLOAT) AS value FROM memopol_settings_setting WHERE key = 'SCORE_DECAY_DENOM') decay_denom ON 1=1
JOIN (SELECT CAST(TO_NUMBER(value, '99999') AS FLOAT) AS value FROM memopol_settings_setting WHERE key = 'SCORE_EXPONENT') exponent ON 1=1
JOIN (SELECT CAST(TO_NUMBER(value, '99999') AS INTEGER) AS value FROM memopol_settings_setting WHERE key = 'SCORE_DECIMALS') decimals ON 1=1
JOIN representatives_votes_proposal ON representatives_votes_vote.proposal_id = representatives_votes_proposal.id
LEFT JOIN representatives_recommendations_recommendation ON representatives_votes_proposal.id = representatives_recommendations_recommendation.proposal_id
WHERE representatives_recommendations_recommendation.id IS NOT NULL;
"""
),
migrations.RunSQL(
"""
CREATE VIEW "representatives_recommendations_dossierscores"
AS SELECT
"representatives_recommendations_votescores"."representative_id" || ':' || "representatives_votes_proposal"."dossier_id" AS "id",
"representatives_recommendations_votescores"."representative_id",
"representatives_votes_proposal"."dossier_id",
SUM("representatives_recommendations_votescores"."score") AS "score"
FROM "representatives_recommendations_votescores"
INNER JOIN "representatives_votes_proposal"
ON ( "representatives_recommendations_votescores"."proposal_id" = "representatives_votes_proposal"."id" )
GROUP BY
"representatives_recommendations_votescores"."representative_id",
"representatives_votes_proposal"."dossier_id"
"""
),
migrations.RunSQL(
"""
CREATE VIEW "representatives_recommendations_representativescore"
AS SELECT
"representatives_representative"."id" as "representative_id",
COALESCE(SUM("representatives_recommendations_votescores"."score"), 0) AS "score"
FROM
"representatives_representative"
LEFT OUTER JOIN "representatives_recommendations_votescores"
ON "representatives_recommendations_votescores"."representative_id" = "representatives_representative"."id"
GROUP BY "representatives_representative"."id"
"""
)
]
...@@ -12,7 +12,7 @@ class DossierScore(models.Model): ...@@ -12,7 +12,7 @@ class DossierScore(models.Model):
representative = models.ForeignKey(Representative, representative = models.ForeignKey(Representative,
on_delete=models.DO_NOTHING) on_delete=models.DO_NOTHING)
dossier = models.ForeignKey(Dossier, on_delete=models.DO_NOTHING) dossier = models.ForeignKey(Dossier, on_delete=models.DO_NOTHING)
score = models.IntegerField(default=0) score = models.FloatField(default=0)
class Meta: class Meta:
managed = False managed = False
...@@ -25,7 +25,7 @@ class VoteScore(models.Model): ...@@ -25,7 +25,7 @@ class VoteScore(models.Model):
representative = models.ForeignKey( representative = models.ForeignKey(
Representative, related_name='votescores', null=True) Representative, related_name='votescores', null=True)
position = models.CharField(max_length=10) position = models.CharField(max_length=10)
score = models.IntegerField(default=0) score = models.FloatField(default=0)
class Meta: class Meta:
managed = False managed = False
...@@ -36,7 +36,7 @@ class VoteScore(models.Model): ...@@ -36,7 +36,7 @@ class VoteScore(models.Model):
class RepresentativeScore(models.Model): class RepresentativeScore(models.Model):
representative = models.OneToOneField('representatives.representative', representative = models.OneToOneField('representatives.representative',
primary_key=True, related_name='score') primary_key=True, related_name='score')
score = models.IntegerField(default=0) score = models.FloatField(default=0)
class Meta: class Meta:
managed = False managed = False
...@@ -52,7 +52,7 @@ class Recommendation(models.Model): ...@@ -52,7 +52,7 @@ class Recommendation(models.Model):
recommendation = models.CharField(max_length=10, choices=Vote.VOTECHOICES) recommendation = models.CharField(max_length=10, choices=Vote.VOTECHOICES)
title = models.CharField(max_length=1000, blank=True) title = models.CharField(max_length=1000, blank=True)
description = models.TextField(blank=True) description = models.TextField(blank=True)
weight = models.IntegerField(default=0) weight = models.FloatField(default=0)
class Meta: class Meta:
ordering = ['proposal__datetime'] ordering = ['proposal__datetime']
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter