diff --git a/geogame/main/migrations/0006_auto_20200610_1501.py b/geogame/main/migrations/0006_auto_20200610_1501.py new file mode 100644 index 0000000..3d08972 --- /dev/null +++ b/geogame/main/migrations/0006_auto_20200610_1501.py @@ -0,0 +1,22 @@ +# Generated by Django 2.2.4 on 2020-06-10 15:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0005_auto_20200117_0023'), + ] + + operations = [ + migrations.RemoveField( + model_name='challenge', + name='average', + ), + migrations.AlterField( + model_name='challenge', + name='name', + field=models.CharField(blank=True, db_index=True, max_length=255, verbose_name='Challenge Name'), + ), + ] diff --git a/geogame/main/models.py b/geogame/main/models.py index ff55876..7d10d78 100644 --- a/geogame/main/models.py +++ b/geogame/main/models.py @@ -1,6 +1,7 @@ import os import random import uuid +import math from django.contrib.postgres.search import SearchVectorField, SearchQuery, SearchVector from django.conf import settings @@ -51,20 +52,14 @@ class User(AbstractUser): class Challenge(models.Model): - name = models.CharField(_('Challenge Name'), max_length=255, blank=False, db_index=True) - average = models.PositiveIntegerField(default=0) + name = models.CharField(_('Challenge Name'), max_length=255, blank=True, db_index=True) user = models.ForeignKey(User, models.PROTECT, related_name='challenge_user', null=False, blank=False) - def update_average_score(self): - average = GameRound.objects.filter(game__challenge=self).aggregate(Avg('result')).get('result__avg', 0) - self.average = average - self.save() - return average - def setup_challenge(self, user): rounds = Coord.objects.filter(challenge=self) + #setup games with max score game = Game.objects.create( challenge=self, start=timezone.now(), @@ -82,6 +77,18 @@ class Challenge(models.Model): round_id = round.id return game.id, round_id + @property + def average(self): + #this should be cached, but with low volumes its fine as is + return int(round(Game.objects.filter(challenge=self).aggregate(Avg('score')).get('score__avg', 0))) + + @property + def num_rounds(self): + return Coord.objects.filter(challenge=self).count() + + def num_plays(self): + return Game.objects.filter(challenge=self).count() + class Coord(models.Model): lng = models.CharField(_('longitude'), max_length=50, null=False, blank=False) @@ -132,5 +139,13 @@ class GameRound(models.Model): else: actual_coord = (self.coord.lat, self.coord.lng,) guess_coord = (self.guess_lat, self.guess_lng,) - self.result = distance.distance(actual_coord, guess_coord).km * 1000 - super().save(*args, **kwargs) + #get distance in meters between actual coord and the guess + dst = distance.distance(actual_coord, guess_coord).km * 1000 + #calculate a score of 0 to 100 + if dst < 100: + self.result = 100 + elif dst > 100000: + self.result = 0 + else: + self.result = int(round(14.46 * (11.52 - math.log(dst)))) + super().save(*args, **kwargs) \ No newline at end of file diff --git a/geogame/main/views.py b/geogame/main/views.py index 41be95c..d4a971c 100644 --- a/geogame/main/views.py +++ b/geogame/main/views.py @@ -118,6 +118,7 @@ class EditChallengeView(views.UserPassesTestMixin, TemplateView): context['challenge'] = challenge context['formset'] = ChallengeCoordFormSet(queryset=Coord.objects.none()) context['coords'] = Coord.objects.filter(challenge=challenge) + #add form so users can edit the challenge name return context def post(self, *args, **kwargs): @@ -161,7 +162,7 @@ class ChallengeListView(views.LoginRequiredMixin, ListView): values('challenge').\ distinct() - return Challenge.objects.filter(id__in=ids).order_by('average') + return Challenge.objects.filter(id__in=ids).order_by('id') class NewGameView(views.LoginRequiredMixin, View): @@ -241,6 +242,7 @@ class RoundView(views.UserPassesTestMixin, UpdateView): ) ) + class RemoveCoordView(View): def post(self, request, *args, **kwargs): round = get_object_or_404(GameRound, pk=self.kwargs.get('round_pk', 0)) @@ -249,7 +251,7 @@ class RemoveCoordView(View): dodgy_coord.report() if game.challenge: - round.score = 30000 + round.score = 100 round.guess_lat = 0 round.guess_lng = 0 round.save() @@ -269,7 +271,6 @@ class RemoveCoordView(View): ) ) else: - round.game.challenge.update_average_score() return redirect( reverse_lazy( 'game:end-recap-view', @@ -320,7 +321,7 @@ class RoundRecapView(views.UserPassesTestMixin, TemplateView): context['guess_lat'] = round.guess_lat context['guess_lng'] = round.guess_lng context['game_id'] = round.game.id - context['distance'] = int(round.result) + context['result'] = round.result next_round = GameRound.objects.filter( game=round.game, @@ -328,11 +329,6 @@ class RoundRecapView(views.UserPassesTestMixin, TemplateView): ).first() if not next_round: - #not every game is part of a challenge, so try updated the challenge average - try: - round.game.challenge.update_average_score() - except: - pass context['last_round'] = True else: context['next_round_id'] = next_round.id @@ -361,14 +357,10 @@ class GameRecapView(views.UserPassesTestMixin, TemplateView): ) context['results'] = coord_results - context['average_distance'] = int( - GameRound.objects.filter(game=game)\ - .aggregate(Avg('result'))\ - .get('result__avg', 0) - ) + context['total_score'] = game.score # not every game is part of a challenge, so keep this in a try try: - context['all_average'] = game.challenge.average + context['all_average'] = game.challenge.average() except: pass return context \ No newline at end of file diff --git a/geogame/settings.py b/geogame/settings.py index b433889..00193d0 100644 --- a/geogame/settings.py +++ b/geogame/settings.py @@ -24,7 +24,7 @@ with open(os.path.join(BASE_DIR, "env_secret_key.txt")) as secret_key: SECRET_KEY = secret_key.read().strip() # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = False +DEBUG = True ALLOWED_HOSTS = ['*'] diff --git a/geogame/templates/main/challenge_list.html b/geogame/templates/main/challenge_list.html index 03340a0..c693907 100644 --- a/geogame/templates/main/challenge_list.html +++ b/geogame/templates/main/challenge_list.html @@ -15,12 +15,16 @@ Name Average + Rounds + Plays {% for challenge in challenges %} {{challenge.name}} - {{challenge.average|intcomma}} + {{challenge.average}} + {{challenge.num_rounds}} + {{challenge.num_plays}} Play {% endfor %} diff --git a/geogame/templates/main/create_challenge_form.html b/geogame/templates/main/create_challenge_form.html index e26205e..35acd01 100644 --- a/geogame/templates/main/create_challenge_form.html +++ b/geogame/templates/main/create_challenge_form.html @@ -15,7 +15,7 @@ {{ form.non_field_errors }} {% csrf_token %}
- +
{{form.name}}
diff --git a/geogame/templates/main/game_recap.html b/geogame/templates/main/game_recap.html index 82d9703..3653a15 100644 --- a/geogame/templates/main/game_recap.html +++ b/geogame/templates/main/game_recap.html @@ -14,7 +14,7 @@ {% endif %}
- Your average guess was {{average_distance|intcomma}}m away.{% if all_average %} The average for this challenge is {{all_average|intcomma}}m{%endif%} + Your total score was {{total_score}}.{% if all_average %} The average for this challenge is {{all_average}}{%endif%}
diff --git a/geogame/templates/main/round_recap.html b/geogame/templates/main/round_recap.html index 849e3f7..e47e1b4 100644 --- a/geogame/templates/main/round_recap.html +++ b/geogame/templates/main/round_recap.html @@ -14,7 +14,7 @@ {% endif %}
- Your guess was {{distance|intcomma}}m away. + You scored {{result}} out of 100.
diff --git a/requirements.txt b/requirements.txt index 0b33ec8..8e3d468 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,6 +6,7 @@ django-allauth==0.39.1 django-autocomplete-light==3.4.1 django-braces==1.13.0 django-countries==5.4 +django-dynamic-formsets==0.0.8 django-extensions==2.2.1 django-starfield==1.0.post1 geographiclib==1.49