Add cache wrapper
This commit is contained in:
parent
9d645841ae
commit
57a6233779
5 changed files with 145 additions and 119 deletions
|
@ -13,7 +13,7 @@ from django.utils.translation import gettext as _, gettext_noop
|
|||
|
||||
from judge.models import Problem, Submission
|
||||
from judge.ml.collab_filter import CollabFilter
|
||||
|
||||
from judge.caching import cache_wrapper
|
||||
|
||||
__all__ = [
|
||||
"contest_completed_ids",
|
||||
|
@ -57,61 +57,52 @@ def contest_completed_ids(participation):
|
|||
return result
|
||||
|
||||
|
||||
@cache_wrapper(prefix="user_complete", timeout=86400)
|
||||
def user_completed_ids(profile):
|
||||
key = "user_complete:%d" % profile.id
|
||||
result = cache.get(key)
|
||||
if result is None:
|
||||
result = set(
|
||||
Submission.objects.filter(
|
||||
user=profile, result="AC", points=F("problem__points")
|
||||
)
|
||||
.values_list("problem_id", flat=True)
|
||||
.distinct()
|
||||
result = set(
|
||||
Submission.objects.filter(
|
||||
user=profile, result="AC", points=F("problem__points")
|
||||
)
|
||||
cache.set(key, result, 86400)
|
||||
.values_list("problem_id", flat=True)
|
||||
.distinct()
|
||||
)
|
||||
return result
|
||||
|
||||
|
||||
@cache_wrapper(prefix="contest_attempted", timeout=86400)
|
||||
def contest_attempted_ids(participation):
|
||||
key = "contest_attempted:%s" % participation.id
|
||||
result = cache.get(key)
|
||||
if result is None:
|
||||
result = {
|
||||
id: {"achieved_points": points, "max_points": max_points}
|
||||
for id, max_points, points in (
|
||||
participation.submissions.values_list(
|
||||
"problem__problem__id", "problem__points"
|
||||
)
|
||||
.annotate(points=Max("points"))
|
||||
.filter(points__lt=F("problem__points"))
|
||||
result = {
|
||||
id: {"achieved_points": points, "max_points": max_points}
|
||||
for id, max_points, points in (
|
||||
participation.submissions.values_list(
|
||||
"problem__problem__id", "problem__points"
|
||||
)
|
||||
}
|
||||
cache.set(key, result, 86400)
|
||||
.annotate(points=Max("points"))
|
||||
.filter(points__lt=F("problem__points"))
|
||||
)
|
||||
}
|
||||
return result
|
||||
|
||||
|
||||
@cache_wrapper(prefix="user_attempted", timeout=86400)
|
||||
def user_attempted_ids(profile):
|
||||
key = "user_attempted:%s" % profile.id
|
||||
result = cache.get(key)
|
||||
if result is None:
|
||||
result = {
|
||||
id: {
|
||||
"achieved_points": points,
|
||||
"max_points": max_points,
|
||||
"last_submission": last_submission,
|
||||
"code": problem_code,
|
||||
"name": problem_name,
|
||||
}
|
||||
for id, max_points, problem_code, problem_name, points, last_submission in (
|
||||
Submission.objects.filter(user=profile)
|
||||
.values_list(
|
||||
"problem__id", "problem__points", "problem__code", "problem__name"
|
||||
)
|
||||
.annotate(points=Max("points"), last_submission=Max("id"))
|
||||
.filter(points__lt=F("problem__points"))
|
||||
)
|
||||
result = {
|
||||
id: {
|
||||
"achieved_points": points,
|
||||
"max_points": max_points,
|
||||
"last_submission": last_submission,
|
||||
"code": problem_code,
|
||||
"name": problem_name,
|
||||
}
|
||||
cache.set(key, result, 86400)
|
||||
for id, max_points, problem_code, problem_name, points, last_submission in (
|
||||
Submission.objects.filter(user=profile)
|
||||
.values_list(
|
||||
"problem__id", "problem__points", "problem__code", "problem__name"
|
||||
)
|
||||
.annotate(points=Max("points"), last_submission=Max("id"))
|
||||
.filter(points__lt=F("problem__points"))
|
||||
)
|
||||
}
|
||||
return result
|
||||
|
||||
|
||||
|
@ -174,77 +165,67 @@ def editable_problems(user, profile=None):
|
|||
return subquery
|
||||
|
||||
|
||||
@cache_wrapper(prefix="hp", timeout=900)
|
||||
def hot_problems(duration, limit):
|
||||
cache_key = "hot_problems:%d:%d" % (duration.total_seconds(), limit)
|
||||
qs = cache.get(cache_key)
|
||||
if qs is None:
|
||||
qs = Problem.get_public_problems().filter(
|
||||
submission__date__gt=timezone.now() - duration
|
||||
)
|
||||
qs0 = (
|
||||
qs.annotate(k=Count("submission__user", distinct=True))
|
||||
.order_by("-k")
|
||||
.values_list("k", flat=True)
|
||||
)
|
||||
qs = Problem.get_public_problems().filter(
|
||||
submission__date__gt=timezone.now() - duration
|
||||
)
|
||||
qs0 = (
|
||||
qs.annotate(k=Count("submission__user", distinct=True))
|
||||
.order_by("-k")
|
||||
.values_list("k", flat=True)
|
||||
)
|
||||
|
||||
if not qs0:
|
||||
return []
|
||||
# make this an aggregate
|
||||
mx = float(qs0[0])
|
||||
if not qs0:
|
||||
return []
|
||||
# make this an aggregate
|
||||
mx = float(qs0[0])
|
||||
|
||||
qs = qs.annotate(unique_user_count=Count("submission__user", distinct=True))
|
||||
# fix braindamage in excluding CE
|
||||
qs = qs.annotate(
|
||||
submission_volume=Count(
|
||||
Case(
|
||||
When(submission__result="AC", then=1),
|
||||
When(submission__result="WA", then=1),
|
||||
When(submission__result="IR", then=1),
|
||||
When(submission__result="RTE", then=1),
|
||||
When(submission__result="TLE", then=1),
|
||||
When(submission__result="OLE", then=1),
|
||||
output_field=FloatField(),
|
||||
)
|
||||
qs = qs.annotate(unique_user_count=Count("submission__user", distinct=True))
|
||||
# fix braindamage in excluding CE
|
||||
qs = qs.annotate(
|
||||
submission_volume=Count(
|
||||
Case(
|
||||
When(submission__result="AC", then=1),
|
||||
When(submission__result="WA", then=1),
|
||||
When(submission__result="IR", then=1),
|
||||
When(submission__result="RTE", then=1),
|
||||
When(submission__result="TLE", then=1),
|
||||
When(submission__result="OLE", then=1),
|
||||
output_field=FloatField(),
|
||||
)
|
||||
)
|
||||
qs = qs.annotate(
|
||||
ac_volume=Count(
|
||||
Case(
|
||||
When(submission__result="AC", then=1),
|
||||
output_field=FloatField(),
|
||||
)
|
||||
)
|
||||
qs = qs.annotate(
|
||||
ac_volume=Count(
|
||||
Case(
|
||||
When(submission__result="AC", then=1),
|
||||
output_field=FloatField(),
|
||||
)
|
||||
)
|
||||
qs = qs.filter(unique_user_count__gt=max(mx / 3.0, 1))
|
||||
)
|
||||
qs = qs.filter(unique_user_count__gt=max(mx / 3.0, 1))
|
||||
|
||||
qs = (
|
||||
qs.annotate(
|
||||
ordering=ExpressionWrapper(
|
||||
0.02
|
||||
* F("points")
|
||||
* (
|
||||
0.4 * F("ac_volume") / F("submission_volume")
|
||||
+ 0.6 * F("ac_rate")
|
||||
)
|
||||
+ 100 * e ** (F("unique_user_count") / mx),
|
||||
output_field=FloatField(),
|
||||
)
|
||||
qs = (
|
||||
qs.annotate(
|
||||
ordering=ExpressionWrapper(
|
||||
0.02
|
||||
* F("points")
|
||||
* (0.4 * F("ac_volume") / F("submission_volume") + 0.6 * F("ac_rate"))
|
||||
+ 100 * e ** (F("unique_user_count") / mx),
|
||||
output_field=FloatField(),
|
||||
)
|
||||
.order_by("-ordering")
|
||||
.defer("description")[:limit]
|
||||
)
|
||||
|
||||
cache.set(cache_key, qs, 900)
|
||||
.order_by("-ordering")
|
||||
.defer("description")[:limit]
|
||||
)
|
||||
return qs
|
||||
|
||||
|
||||
@cache_wrapper(prefix="grp", timeout=26400)
|
||||
def get_related_problems(profile, problem, limit=8):
|
||||
if not profile or not settings.ML_OUTPUT_PATH:
|
||||
return None
|
||||
cache_key = "related_problems:%d:%d" % (profile.id, problem.id)
|
||||
qs = cache.get(cache_key)
|
||||
if qs is not None:
|
||||
return qs
|
||||
problemset = Problem.get_visible_problems(profile.user).values_list("id", flat=True)
|
||||
problemset = problemset.exclude(id__in=user_completed_ids(profile))
|
||||
problemset = problemset.exclude(id=problem.id)
|
||||
|
@ -254,8 +235,16 @@ def get_related_problems(profile, problem, limit=8):
|
|||
) + cf_model.problem_neighbors(problem, problemset, CollabFilter.COSINE, limit)
|
||||
results = list(set([i[1] for i in results]))
|
||||
seed = datetime.now().strftime("%d%m%Y")
|
||||
random.Random(seed).shuffle(results)
|
||||
random.shuffle(results)
|
||||
results = results[:limit]
|
||||
results = [Problem.objects.get(id=i) for i in results]
|
||||
cache.set(cache_key, results, 21600)
|
||||
return results
|
||||
|
||||
|
||||
def finished_submission(sub):
|
||||
keys = ["user_complete:%d" % sub.user_id, "user_attempted:%s" % sub.user_id]
|
||||
if hasattr(sub, "contest"):
|
||||
participation = sub.contest.participation
|
||||
keys += ["contest_complete:%d" % participation.id]
|
||||
keys += ["contest_attempted:%d" % participation.id]
|
||||
cache.delete_many(keys)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue