87 lines
3.3 KiB
Python
87 lines
3.3 KiB
Python
|
|
from files.classes.comment import Comment
|
|
from files.classes.volunteer_janitor import VolunteerJanitorRecord, VolunteerJanitorResult
|
|
from files.helpers.math import saturate, remap
|
|
|
|
# Returns (IsBad, Confidence)
|
|
def evaluate_badness_of(choice):
|
|
if choice == VolunteerJanitorResult.Warning:
|
|
return True, 1
|
|
if choice == VolunteerJanitorResult.Ban:
|
|
return True, 1
|
|
|
|
# treating this like a low-weight bad response
|
|
if choice == VolunteerJanitorResult.Bad:
|
|
return True, 0.5
|
|
|
|
# treating this like a low-weight not-bad response
|
|
if choice == VolunteerJanitorResult.Neutral:
|
|
return False, 0.5
|
|
|
|
return False, 1
|
|
|
|
def userweight_from_user_accuracy(accuracy):
|
|
return saturate(remap(accuracy, 0.5, 1, 0, 1))
|
|
|
|
def calculate_final_comment_badness(comment_total, comment_weight, conservative):
|
|
if not conservative:
|
|
# insert an artificial 50%-badness confident vote, to prevent us from ever reaching 1.0 or 0.0
|
|
return (comment_total + 0.5) / (comment_weight + 1.0)
|
|
|
|
if comment_weight == 0:
|
|
# INSUFFICIENT DATA FOR A MEANINGFUL ANSWER
|
|
return 0.5
|
|
|
|
original_badness = calculate_final_comment_badness(comment_total, comment_weight, False)
|
|
if original_badness > 0.5:
|
|
# fake a not-bad vote, with the confidence being the opposite of our confidence in it being bad
|
|
# don't let it invert though
|
|
forged_weight = 1.0 - original_badness
|
|
calculated_badness = max(comment_total / (comment_weight + forged_weight), 0.5)
|
|
else:
|
|
# fake a bad vote, with the confidence being the opposite of our confidence in it being not-bad
|
|
# don't let it invert though
|
|
forged_weight = original_badness
|
|
calculated_badness = min((comment_total + forged_weight) / (comment_weight + forged_weight), 0.5)
|
|
|
|
return calculated_badness
|
|
|
|
def update_comment_badness(db, cid, diagnostics: bool = False):
|
|
# Recalculate the comment's confidence values
|
|
# This probably does more SQL queries than it should
|
|
records = db.query(VolunteerJanitorRecord) \
|
|
.where(VolunteerJanitorRecord.comment_id == cid) \
|
|
.order_by(VolunteerJanitorRecord.recorded_datetimez)
|
|
|
|
user_has_pending = {}
|
|
earliest_submission = {}
|
|
|
|
for rec in records:
|
|
if rec.result == VolunteerJanitorResult.Pending:
|
|
user_has_pending[rec.user_id] = True
|
|
else:
|
|
if rec.user_id in user_has_pending:
|
|
if rec.user_id not in earliest_submission or earliest_submission[rec.user_id].recorded_datetimez > rec.recorded_datetimez:
|
|
earliest_submission[rec.user_id] = rec
|
|
|
|
badness = 0
|
|
weight = 0
|
|
|
|
for submission in earliest_submission.values():
|
|
userweight_user = userweight_from_user_accuracy(submission.user.volunteer_janitor_correctness);
|
|
submission_bad, submission_weight = evaluate_badness_of(submission.result)
|
|
|
|
additive_weight = submission_weight * userweight_user
|
|
|
|
weight += additive_weight
|
|
if submission_bad:
|
|
badness += additive_weight
|
|
|
|
comment_badness = calculate_final_comment_badness(badness, weight, True)
|
|
|
|
db.query(Comment) \
|
|
.where(Comment.id == cid) \
|
|
.update({Comment.volunteer_janitor_badness: comment_badness})
|
|
|
|
if diagnostics:
|
|
print(f"Updated comment {cid} to {comment_badness}")
|