Commit e4312d67 by Victor Shnayder

work in progress on supporting science puzzles

parent 723012b2
......@@ -25,6 +25,36 @@ class Score(models.Model):
score_version = models.IntegerField()
created = models.DateTimeField(auto_now_add=True)
@staticmethod
def display_score(score):
"""
Argument:
score (float), as stored in the DB
Returns:
score (float), as displayed to the user in the game and in the leaderboard
"""
# TODO: put in correct formula
return -score
@staticmethod
def get_top_n(puzzle_id, n):
"""
Arguments:
puzzle_id (int): id of the puzzle for which to look
n (int): number of top scores to return.
Returns:
The top (lowest energy, highest display score) n scores for the puzzle. If
there are fewer than n, returns all. Output is a list of dictionaries, sorted
by display_score:
[ {username: 'a_user',
score: 8500}, ...]
"""
scores = Score.objects.filter(puzzle_id=puzzle_id).order_by('-best_score')[:n]
return [{'username': s.user.username, 'score': display_score(s.best_score)}
for s in scores]
class PuzzleComplete(models.Model):
"""
......
......@@ -9,7 +9,7 @@ from django.conf import settings
from django.core.urlresolvers import reverse
from foldit.views import foldit_ops, verify_code
from foldit.models import PuzzleComplete
from foldit.models import PuzzleComplete, Score
from student.models import UserProfile, unique_id_for_user
from datetime import datetime, timedelta
......@@ -37,13 +37,19 @@ class FolditTestCase(TestCase):
request.user = self.user
return request
def test_SetPlayerPuzzleScores(self):
scores = [ {"PuzzleID": 994391,
def make_puzzle_score_request(self, puzzle_ids, best_scores):
"""
Given lists of puzzle_ids and best_scores (must have same length), make a
SetPlayerPuzzleScores request and return the response.
"""
def score_dict(puzzle_id, best_score):
return {"PuzzleID": puzzle_id,
"ScoreType": "score",
"BestScore": 0.078034,
"CurrentScore":0.080035,
"ScoreVersion":23}]
"BestScore": best_score,
# current scores don't actually matter
"CurrentScore": best_score + 0.01,
"ScoreVersion": 23}
scores = [score_dict(pid, bs) for pid, bs in zip(puzzle_ids, best_scores)]
scores_str = json.dumps(scores)
verify = {"Verify": verify_code(self.user.email, scores_str),
......@@ -55,51 +61,76 @@ class FolditTestCase(TestCase):
response = foldit_ops(request)
self.assertEqual(response.status_code, 200)
return response
def test_SetPlayerPuzzleScores(self):
puzzle_id = 994391
best_score = 0.078034
response = self.make_puzzle_score_request([puzzle_id], [best_score])
self.assertEqual(response.content, json.dumps(
[{"OperationID": "SetPlayerPuzzleScores",
"Value": [{
"PuzzleID": 994391,
"PuzzleID": puzzle_id,
"Status": "Success"}]}]))
# There should now be a score in the db.
top_10 = Score.get_top_n(puzzle_id, 10)
self.assertEqual(len(top_10), 1)
self.assertEqual(top_10[0]['score'], Score.display_score(best_score))
def test_SetPlayerPuzzleScores_many(self):
scores = [ {"PuzzleID": 994391,
"ScoreType": "score",
"BestScore": 0.078034,
"CurrentScore":0.080035,
"ScoreVersion":23},
{"PuzzleID": 994392,
"ScoreType": "score",
"BestScore": 0.078000,
"CurrentScore":0.080011,
"ScoreVersion":23}]
scores_str = json.dumps(scores)
verify = {"Verify": verify_code(self.user.email, scores_str),
"VerifyMethod":"FoldItVerify"}
data = {'SetPlayerPuzzleScoresVerify': json.dumps(verify),
'SetPlayerPuzzleScores': scores_str}
def test_SetPlayerPuzzleScores_many(self):
request = self.make_request(data)
response = foldit_ops(request)
self.assertEqual(response.status_code, 200)
response = self.make_puzzle_score_request([1, 2], [0.078034, 0.080000])
self.assertEqual(response.content, json.dumps(
[{"OperationID": "SetPlayerPuzzleScores",
"Value": [{
"PuzzleID": 994391,
"PuzzleID": 1,
"Status": "Success"},
{"PuzzleID": 994392,
{"PuzzleID": 2,
"Status": "Success"}]}]))
def test_SetPlayerPuzzleScores_multiple(self):
"""
Check that multiple posts with the same id are handled properly
(keep latest for each user, have multiple users work properly)
"""
orig_score = 0.07
puzzle_id = 1
response = self.make_puzzle_score_request([puzzle_id], [orig_score])
# There should now be a score in the db.
top_10 = Score.get_top_n(puzzle_id, 10)
self.assertEqual(len(top_10), 1)
self.assertEqual(top_10[0]['score'], Score.display_score(best_score))
# Reporting a better score should overwrite
better_score = 0.06
response = self.make_puzzle_score_request([1], [better_score])
top_10 = Score.get_top_n(puzzle_id, 10)
self.assertEqual(len(top_10), 1)
self.assertEqual(top_10[0]['score'], Score.display_score(better_score))
# reporting a worse score shouldn't
worse_score = 0.065
response = self.make_puzzle_score_request([1], [worse_score])
top_10 = Score.get_top_n(puzzle_id, 10)
self.assertEqual(len(top_10), 1)
# should still be the better score
self.assertEqual(top_10[0]['score'], Score.display_score(better_score))
def test_SetPlayerPuzzleScores_error(self):
scores = [ {"PuzzleID": 994391,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment