rDrama/files/helpers/volunteer_janitor.py

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}")