in api/models/badge.py [0:0]
def handleAsync(self):
one_week_ago = datetime.datetime.now() - datetime.timedelta(days=7)
badges_to_remove = []
badges_to_add = []
users = self.dbs.query(User)
badges = self.dbs.query(Badge)
examples = self.dbs.query(Example)
validations = self.dbs.query(Validation)
validations_by_eid = {}
for validation in validations:
if validation.eid in validations_by_eid:
validations_by_eid[validation.eid].append(validation)
else:
validations_by_eid[validation.eid] = [validation]
badges_and_examples_by_uid = {}
for badge in badges:
if badge.uid in badges_and_examples_by_uid:
badges_and_examples_by_uid[badge.uid]["badges"].append(badge)
else:
badges_and_examples_by_uid[badge.uid] = {
"badges": [badge],
"examples": [],
}
num_created_by_uid = {}
max_num_created = 0
for example in examples:
if example.generated_datetime > one_week_ago:
if example.uid in num_created_by_uid:
num_created_by_uid[example.uid] += 1
else:
num_created_by_uid[example.uid] = 1
if num_created_by_uid[example.uid] > max_num_created:
max_num_created = num_created_by_uid[example.uid]
if example.uid in badges_and_examples_by_uid:
badges_and_examples_by_uid[example.uid]["examples"].append(example)
else:
badges_and_examples_by_uid[example.uid] = {
"badges": [],
"examples": [example],
}
weekly_winners = [
uid
for uid, num_created in num_created_by_uid.items()
if num_created == max_num_created
]
for user in users:
if user.metadata_json:
metadata = util.json_decode(user.metadata_json)
else:
metadata = {}
async_badges_to_award = []
# Recompute all example streaks for a user.
recomputed_example_streak_badge_names = []
recomputed_day_streak_badge_names = []
if user.id in badges_and_examples_by_uid:
user_examples = badges_and_examples_by_uid[user.id]["examples"]
if len(user_examples) > 0:
example_streak_count = 0
day_streak_count = 0
previous_example_day = user_examples[0].generated_datetime
for example in user_examples:
if example.context:
task = example.context.round.task
if example.id in validations_by_eid:
example_validations = validations_by_eid[example.id]
else:
example_validations = []
if example.context and (
not example.model_wrong
or example.retracted
or self.lengthOfFilteredList(
lambda validation: validation.label.name == "flagged",
example_validations,
)
>= task.num_matching_validations
or self.lengthOfFilteredList(
lambda validation: validation.label.name == "incorrect",
example_validations,
)
>= task.num_matching_validations
or self.lengthOfFilteredList(
lambda validation: validation.label.name == "flagged"
and validation.mode.name == "owner",
example_validations,
)
>= 1
or self.lengthOfFilteredList(
lambda validation: validation.label.name == "incorrect"
and validation.mode.name == "owner",
example_validations,
)
>= 1
):
example_streak_count = 0
else:
example_streak_count += 1
one_day_passed = previous_example_day + datetime.timedelta(
days=1
)
two_days_passed = previous_example_day + datetime.timedelta(
days=2
)
if example.generated_datetime > one_day_passed:
if example.generated_datetime <= two_days_passed:
day_streak_count += 1
for (
streak_type,
num_required,
) in self.day_streak_type_and_num_required_days:
if day_streak_count == num_required:
recomputed_day_streak_badge_names.append(
"DAY_STREAK_" + streak_type
)
elif example.generated_datetime > two_days_passed:
day_streak_count = 0
previous_example_day = example.generated_datetime
if example_streak_count in self.example_streak_num_required:
recomputed_example_streak_badge_names.append(
"EXAMPLE_STREAK_" + str(example_streak_count)
)
user.streak_examples = example_streak_count
user.streak_days = day_streak_count
# Remove a user's undeserved badges.
for badge in badges_and_examples_by_uid[user.id]["badges"]:
for num_required in self.example_streak_num_required:
if badge.name == "EXAMPLE_STREAK_" + str(num_required):
if badge.name in recomputed_example_streak_badge_names:
recomputed_example_streak_badge_names.remove(badge.name)
else:
badges_to_remove.append(badge)
for (
streak_type,
num_required,
) in self.day_streak_type_and_num_required_days:
if badge.name == "DAY_STREAK_" + streak_type:
if badge.name in recomputed_day_streak_badge_names:
recomputed_day_streak_badge_names.remove(badge.name)
else:
badges_to_remove.append(badge)
num_created_by_task = self.getFieldsFromMetadata(
metadata,
0,
[
task_name + "_fooling_no_verified_incorrect_or_flagged"
for task_name in self.task_code_to_badge_name
],
)
for (
contributor_type,
num_required_creations,
_,
) in self.contributor_type_num_required_creations_and_validations:
if badge.name == "DYNABENCH_" + contributor_type:
if sum(num_created_by_task) < num_required_creations:
badges_to_remove.append(badge)
if badge.name == "ALL_TASKS_COVERED" and 0 in num_created_by_task:
badges_to_remove.append(badge)
for task_name in self.task_code_to_badge_name:
for (
contributor_type,
num_required_creations,
) in self.task_contributor_type_and_num_required_creations:
if (
badge.name
== "DYNABENCH_"
+ self.task_code_to_badge_name[task_name]
+ "_"
+ contributor_type
):
if (
task_name
+ "_fooling_no_verified_incorrect_or_flagged"
in metadata
):
if (
metadata[
task_name
+ "_fooling_no_verified_incorrect_"
+ "or_flagged"
]
< num_required_creations
):
badges_to_remove.append(badge)
else:
badges_to_remove.append(badge)
else:
badges_and_examples_by_uid[user.id] = {"badges": [], "examples": []}
# Award streak badges that result from the removal of other streak badges.
# (e.g., if a 20 example streak is undeserved, a 5 example streak might
# be deserved instead)
for badge_name in recomputed_example_streak_badge_names:
async_badges_to_award.append(badge_name)
for badge_name in recomputed_day_streak_badge_names:
async_badges_to_award.append(badge_name)
# Award badges that must be computed asynchronously.
if user.total_verified_fooled > 0 and "FIRST_VALIDATED_FOOLING" not in [
badge.name for badge in badges_and_examples_by_uid[user.id]["badges"]
]:
async_badges_to_award.append("FIRST_VALIDATED_FOOLING")
if (
len(badges_and_examples_by_uid[user.id]["examples"]) > 1
and badges_and_examples_by_uid[user.id]["examples"][
-1
].generated_datetime
- badges_and_examples_by_uid[user.id]["examples"][0].generated_datetime
> datetime.timedelta(days=1)
and "FIRST_STEPS"
not in [
badge.name
for badge in badges_and_examples_by_uid[user.id]["badges"]
]
):
async_badges_to_award.append("FIRST_STEPS")
if user.id in weekly_winners and datetime.date.today().weekday() == 0:
async_badges_to_award.append("WEEKLY_WINNER")
for name in async_badges_to_award:
badges_to_add.append(self._badgeobj(user.id, name))
if "async_badges_to_award" not in metadata:
metadata["async_badges_to_award"] = async_badges_to_award
else:
metadata["async_badges_to_award"] += async_badges_to_award
user.metadata_json = util.json_encode(metadata)
self.createNotificationsAndRemoveBadges(
badges_to_remove, "BADGE_REMOVED_STREAK"
)
self.createNotificationsAndAddBadges(badges_to_add)
print("Completed job")