Files
geogame/geogame/main/models.py

136 lines
5.1 KiB
Python

import os
import random
import uuid
from django.contrib.postgres.search import SearchVectorField, SearchQuery, SearchVector
from django.conf import settings
from django.db import models, transaction, IntegrityError
from django.db.models import Avg
from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from django.core.validators import FileExtensionValidator
from django.shortcuts import reverse
from django.contrib.auth.models import AbstractUser
from django.utils import timezone
from geopy import distance
class User(AbstractUser):
first_name = models.CharField(_('first name'), max_length=50, blank=True, db_index=True)
last_name = models.CharField(_('last name'), max_length=50, blank=True, db_index=True)
email = models.EmailField(_('email address'), blank=False, null=False, db_index=True)
api_key = models.CharField(_('google maps api key'), max_length=255, blank=True, db_index=True)
display_name = models.CharField(_('display name'), max_length=25, blank=True, db_index=True)
def generate_new_game(self):
game = Game.objects.create(
start=timezone.now(),
user=self,
score=0,
active=True,
)
qs = Coord.objects.filter(reports=0)
coords = qs.order_by('?')[:5]
for i, coord in enumerate(coords):
round = GameRound.objects.create(
game=game,
coord=coord,
order=i,
)
if i == 0:
round_id = round.id
return game.id, round_id
def get_active_game(self):
return Game.objects.filter(user=self, active=True).last()
def deactive_games(self):
return Game.objects.filter(user=self).update(active=False)
class Challenge(models.Model):
name = models.CharField(_('Challenge Name'), max_length=255, blank=True, db_index=True)
average = models.PositiveIntegerField(default=0)
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)
game = Game.objects.create(
challenge=self,
start=timezone.now(),
user=user,
score=0,
active=True,
)
for order, coord in enumerate(rounds):
round = GameRound.objects.create(
game=game,
coord=coord,
order=order
)
if order == 0:
round_id = round.id
return game.id, round_id
class Coord(models.Model):
lng = models.CharField(_('longitude'), max_length=50, null=False, blank=False)
lat = models.CharField(_('latitude'), max_length=50, null=False, blank=False)
user = models.ForeignKey(User, models.PROTECT,
related_name='coord_user',
null=False, blank=False)
reports = models.PositiveIntegerField(default=0)
challenge = models.ForeignKey(Challenge, models.PROTECT,
related_name='coord_challenge',
null=True, blank=True)
def report(self):
self.reports = self.reports + 1
self.save()
class Game(models.Model):
challenge = models.ForeignKey(Challenge, models.PROTECT,
related_name='game_challenge',
null=True, blank=True)
start = models.DateTimeField()
user = models.ForeignKey(User, models.PROTECT,
related_name='game_user',
null=False, blank=False)
score = models.PositiveIntegerField()
active = models.BooleanField()
def get_rounds(self):
return GameRound.objects.filter(game=self)
class GameRound(models.Model):
game = models.ForeignKey(Game, models.PROTECT,
related_name='round_game',
null=False, blank=False)
coord = models.ForeignKey(Coord, models.CASCADE,
related_name='round_coord',
null=False, blank=False)
order = models.IntegerField(_('round order'))
guess_lat = models.CharField(_('latitude'), max_length=50, blank=True, null=True)
guess_lng = models.CharField(_('longitude'), max_length=50, blank=True, null=True)
result = models.PositiveIntegerField(default=0)
def save(self, *args, **kwargs):
if not self.guess_lat or not self.guess_lng:
self.result = 0
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)