Skip to content

Commit

Permalink
Automatically set visibility=0 if application's some criterion is bel…
Browse files Browse the repository at this point in the history
…ow threshold
  • Loading branch information
aapris committed Nov 19, 2024
1 parent 629db72 commit 9a684d4
Showing 1 changed file with 128 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,132 @@
from django.core.management.base import BaseCommand
from django.db import transaction

from application_evaluator.models import ApplicationRound
from application_evaluator.models import ApplicationRound, Application

LOG_DIR = "close_logs"


def sort_groups(groups):
desired_order = ["IMP", "IQE", "EXC", "Co-C", "TEC"]
return dict(
sorted(
groups.items(),
key=lambda x: desired_order.index(x[1]["abbr"]) if x[1]["abbr"] in desired_order else len(desired_order),
)
)


def print_evaluation_table(application_id):
"""
Prints evaluation table for given application showing scores by evaluators and criteria.
Returns False if any group average is below threshold.
"""
from django.db import connection

query = """
WITH evaluator_scores AS (
SELECT
au.first_name || ' ' || au.last_name as evaluator_name,
cg.abbr as group_abbr,
cg.threshold,
c.name as criterion_name,
c.weight,
s.score,
c.id as criterion_id,
cg.id as group_id
FROM application_evaluator_score s
JOIN auth_user au ON s.evaluator_id = au.id
JOIN application_evaluator_criterion c ON s.criterion_id = c.id
JOIN application_evaluator_criteriongroup cg ON c.group_id = cg.id
WHERE s.application_id = %s
ORDER BY au.first_name, cg.abbr, c.name
)
SELECT * FROM evaluator_scores
"""

with connection.cursor() as cursor:
cursor.execute(query, [application_id])
rows = cursor.fetchall()

if not rows:
return True

evaluators = {}
groups = {}
criteria_by_group = {}
has_below_threshold = False

for row in rows:
evaluator_name, group_abbr, threshold, criterion_name, weight, score, criterion_id, group_id = row

if group_id not in groups:
groups[group_id] = {"abbr": group_abbr, "threshold": threshold}
criteria_by_group[group_id] = set()

criteria_by_group[group_id].add(criterion_id)

if evaluator_name not in evaluators:
evaluators[evaluator_name] = {}

if criterion_id not in evaluators[evaluator_name]:
evaluators[evaluator_name][criterion_id] = {"score": score, "group_id": group_id, "weight": weight}
app = Application.objects.get(id=application_id)
print("\nEvaluation Table: ", app.name)
print("-" * 80)

header = "Evaluator"
for group_id, group in groups.items():
header += f"\t{group['abbr']}"
print(header)
print("-" * 80)
groups = sort_groups(groups)
for evaluator_name, scores in evaluators.items():
line = evaluator_name[:24].ljust(24)
for group_id, group in groups.items():
group_scores = [scores.get(crit_id, {"score": 0, "weight": 0}) for crit_id in criteria_by_group[group_id]]

total_weight = sum(score["weight"] for score in group_scores)
if total_weight > 0:
weighted_avg = sum(score["score"] * score["weight"] for score in group_scores) / total_weight
else:
weighted_avg = 0

threshold_marker = "!" if weighted_avg < group["threshold"] else ""
line += f"\t{weighted_avg:.3f}{threshold_marker}"

print(line)

print("-" * 80)
print("Total".ljust(24), end="")
for group_id, group in groups.items():
all_group_scores = []
total_weight = 0

for evaluator_scores in evaluators.values():
for crit_id in criteria_by_group[group_id]:
if crit_id in evaluator_scores:
score_data = evaluator_scores[crit_id]
all_group_scores.append({"score": score_data["score"], "weight": score_data["weight"]})
total_weight += score_data["weight"]

if total_weight > 0:
weighted_avg = sum(score["score"] * score["weight"] for score in all_group_scores) / total_weight
else:
weighted_avg = 0

if weighted_avg < group["threshold"]:
has_below_threshold = True
threshold_marker = "!"
else:
threshold_marker = ""

print(f"\t{weighted_avg:.3f}{threshold_marker}", end="")
print()
print("-" * 80)

return not has_below_threshold


def move_to_tech_evaluation(ar, options):
log = [f"ApplicationRound: {ar.name}"]
# Add current evaluators' email addresses to log
Expand All @@ -23,7 +144,8 @@ def move_to_tech_evaluation(ar, options):
if visible_apps.exists():
log.append("ApplicationRound has visible applications:")
for app in visible_apps:
log.append(f" {app.id}: {app.name}")
will_proceed = print_evaluation_table(app.id)
log.append(f" {app.id}: {app.name} ({app.visibility}) {will_proceed}")
# Remove tech evaluation comments and scores
comments = app.comments.filter(criterion_group__abbr="TEC")
for c in comments:
Expand All @@ -35,7 +157,10 @@ def move_to_tech_evaluation(ar, options):
for s in scores:
log.append(f" Removed: {s}")
s.delete()

will_proceed = print_evaluation_table(app.id)
if will_proceed is False:
app.visibility = 0
app.save()
else:
log.append("ApplicationRound has no visible applications")
return log
Expand Down

0 comments on commit 9a684d4

Please sign in to comment.