# Path: accounts/models.py
# class Team(models.Model, StatsFromChallengesMixin):
#     objects = TeamQuerySet.as_manager()
# 
#     name = models.CharField(max_length=256, unique=True)
#     users = models.ManyToManyField(User, through='accounts.userprofile')
#     created_at = models.DateTimeField(auto_now_add=True, editable=False)
#     created_by = models.ForeignKey(User, related_name='created_team', on_delete=models.CASCADE)
# 
#     @property
#     def num_users(self):
#         return self.users.count()
# 
#     @property
#     def challengesolved_set(self):
#         from challenges.models import ChallengeSolved
#         return ChallengeSolved.objects.filter(user__team=self)
# 
#     @property
#     def solved_challenges(self):
#         from challenges.models import Challenge
#         return Challenge.objects.filter(solved_by__team=self).distinct()
# 
#     @property
#     def failed_challenges(self):
#         from challenges.models import Challenge
#         return Challenge.objects\
#             .filter(failed_by__team=self)\
#             .distinct()\
#             .exclude(pk__in=self.solved_challenges.all())
# 
#     def __str__(self):
#         return self.name
# 
# class UserProfile(models.Model, StatsFromChallengesMixin):
#     objects = UserProfileQuerySet.as_manager()
# 
#     team = models.ForeignKey('accounts.Team', null=True, blank=True, on_delete=models.CASCADE)
#     user = models.OneToOneField(User, related_name='profile', on_delete=models.CASCADE)
#     created_at = models.DateTimeField(auto_now_add=True)
#     image = models.FileField(upload_to='accounts/', default='accounts/user.png')
#     job = models.CharField(max_length=255)
#     gender = models.CharField(max_length=1, choices=(('M', 'Male'), ('F','Female')))
#     website = models.CharField(max_length=255, null=True, blank=True)
#     country = models.ForeignKey(Country, on_delete=models.CASCADE)
#     skills = models.TextField(null=True, blank=True)
# 
#     @property
#     def skill_list(self):
#         return self.skills.split(SKILLS_SEPARATOR) if self.skills else []
# 
#     def __str__(self):
#         return '{}, Team: {}'.format(self.user.username, self.team)
# 
#     @property
#     def failed_challenges(self):
#         return self._all_failed_challenges.exclude(pk__in=self.solved_challenges.all())
# 
# Path: challenges/models.py
# class Category(models.Model):
#     name = models.CharField(max_length=256, unique=True)
#     description = models.TextField()
# 
#     class Meta:
#         verbose_name_plural = "categories"
# 
#     def __str__(self):
#         return self.name
# 
# class Challenge(models.Model):
#     objects = ChallengeQuerySet.as_manager()
# 
#     name = models.CharField(max_length=256)
#     category = models.ForeignKey('challenges.Category', related_name='challenges', on_delete=models.CASCADE)
#     description = models.TextField()
#     key = models.CharField(max_length=256)
#     points = models.IntegerField()
#     difficulty = models.CharField(max_length=1, choices=(
#         ('E', 'Easy'),
#         ('M', 'Medium'),
#         ('H', 'Hard')
#     ))
# 
#     solved_by = models.ManyToManyField(RelatedUserModel,
#                                        related_name='solved_challenges',
#                                        through='challenges.ChallengeSolved')
# 
#     failed_by = models.ManyToManyField(RelatedUserModel,
#                                        related_name='_all_failed_challenges',
#                                        through='challenges.ChallengeFail')
# 
#     @property
#     def newest_solved(self):
#         return self.challengesolved_set.order_by('-datetime')
# 
#     def __str__(self):
#         return self.name
# 
# class ChallengeSolved(models.Model):
#     user = models.ForeignKey(RelatedUserModel, on_delete=models.CASCADE)
#     challenge = models.ForeignKey('challenges.Challenge', on_delete=models.CASCADE)
#     datetime = models.DateTimeField(auto_now_add=True)
# 
#     def __str__(self):
#         return 'Challenge: {}, User: {}'.format(self.challenge.name, self.user)


from itertools import chain, repeat
from cities_light.models import Country
from django.contrib.auth import get_user_model
from django.test import TestCase
from accounts.models import Team, UserProfile
from challenges.models import Category, Challenge, ChallengeSolved

        # create 3 teams: t0, t1, t2
        self.teams = [Team.objects.create(
            name='t{}'.format(i), created_by_id=i+1
        ) for i in range(3)]

        # teams - users association: t0: (u0, u1, u2), t1: (u3, u4, u5), t2: (u6, u7, u8)
        teams_users = chain.from_iterable(repeat(t, 3) for t in self.teams)

        # create users profile
        for u in self.users:
            UserProfile.objects.create(user=u, job='job', gender='M', country=country, team=next(teams_users))

        # create 9 challenges: c0, c1, ..., c8
        self.challenges = [
            Challenge.objects.create(name='c{}'.format(i), points=i, category=test_category)
            for i in range(9)
        ]

        # solved challenges: each user u_i solves all challenges from c_0 to c_i (ie: u2 solves c0,c1,c2)
        for i, u in enumerate(self.users, 1):
            for c in self.challenges[:i]:
                ChallengeSolved.objects.create(user=u.profile, challenge=c)


    def test_users_score(self):
        for i, u in enumerate(UserProfile.objects.annotate_score().all(), 1):
            self.assertEqual(u.points, sum(c.points for c in self.challenges[:i]))

    def test_users_score(self):

# Path: accounts/models.py
# class Team(models.Model, StatsFromChallengesMixin):
#     objects = TeamQuerySet.as_manager()
# 
#     name = models.CharField(max_length=256, unique=True)
#     users = models.ManyToManyField(User, through='accounts.userprofile')
#     created_at = models.DateTimeField(auto_now_add=True, editable=False)
#     created_by = models.ForeignKey(User, related_name='created_team', on_delete=models.CASCADE)
# 
#     @property
#     def num_users(self):
#         return self.users.count()
# 
#     @property
#     def challengesolved_set(self):
#         from challenges.models import ChallengeSolved
#         return ChallengeSolved.objects.filter(user__team=self)
# 
#     @property
#     def solved_challenges(self):
#         from challenges.models import Challenge
#         return Challenge.objects.filter(solved_by__team=self).distinct()
# 
#     @property
#     def failed_challenges(self):
#         from challenges.models import Challenge
#         return Challenge.objects\
#             .filter(failed_by__team=self)\
#             .distinct()\
#             .exclude(pk__in=self.solved_challenges.all())
# 
#     def __str__(self):
#         return self.name
# 
# class UserProfile(models.Model, StatsFromChallengesMixin):
#     objects = UserProfileQuerySet.as_manager()
# 
#     team = models.ForeignKey('accounts.Team', null=True, blank=True, on_delete=models.CASCADE)
#     user = models.OneToOneField(User, related_name='profile', on_delete=models.CASCADE)
#     created_at = models.DateTimeField(auto_now_add=True)
#     image = models.FileField(upload_to='accounts/', default='accounts/user.png')
#     job = models.CharField(max_length=255)
#     gender = models.CharField(max_length=1, choices=(('M', 'Male'), ('F','Female')))
#     website = models.CharField(max_length=255, null=True, blank=True)
#     country = models.ForeignKey(Country, on_delete=models.CASCADE)
#     skills = models.TextField(null=True, blank=True)
# 
#     @property
#     def skill_list(self):
#         return self.skills.split(SKILLS_SEPARATOR) if self.skills else []
# 
#     def __str__(self):
#         return '{}, Team: {}'.format(self.user.username, self.team)
# 
#     @property
#     def failed_challenges(self):
#         return self._all_failed_challenges.exclude(pk__in=self.solved_challenges.all())
# 
# Path: challenges/models.py
# class Category(models.Model):
#     name = models.CharField(max_length=256, unique=True)
#     description = models.TextField()
# 
#     class Meta:
#         verbose_name_plural = "categories"
# 
#     def __str__(self):
#         return self.name
# 
# class Challenge(models.Model):
#     objects = ChallengeQuerySet.as_manager()
# 
#     name = models.CharField(max_length=256)
#     category = models.ForeignKey('challenges.Category', related_name='challenges', on_delete=models.CASCADE)
#     description = models.TextField()
#     key = models.CharField(max_length=256)
#     points = models.IntegerField()
#     difficulty = models.CharField(max_length=1, choices=(
#         ('E', 'Easy'),
#         ('M', 'Medium'),
#         ('H', 'Hard')
#     ))
# 
#     solved_by = models.ManyToManyField(RelatedUserModel,
#                                        related_name='solved_challenges',
#                                        through='challenges.ChallengeSolved')
# 
#     failed_by = models.ManyToManyField(RelatedUserModel,
#                                        related_name='_all_failed_challenges',
#                                        through='challenges.ChallengeFail')
# 
#     @property
#     def newest_solved(self):
#         return self.challengesolved_set.order_by('-datetime')
# 
#     def __str__(self):
#         return self.name
# 
# class ChallengeSolved(models.Model):
#     user = models.ForeignKey(RelatedUserModel, on_delete=models.CASCADE)
#     challenge = models.ForeignKey('challenges.Challenge', on_delete=models.CASCADE)
#     datetime = models.DateTimeField(auto_now_add=True)
# 
#     def __str__(self):
#         return 'Challenge: {}, User: {}'.format(self.challenge.name, self.user)


# Path: SCTF/tests.py
from itertools import chain, repeat
from cities_light.models import Country
from django.contrib.auth import get_user_model
from django.test import TestCase
from accounts.models import Team, UserProfile
from challenges.models import Category, Challenge, ChallengeSolved


        # create 3 teams: t0, t1, t2
        self.teams = [Team.objects.create(
            name='t{}'.format(i), created_by_id=i+1
        ) for i in range(3)]

        # teams - users association: t0: (u0, u1, u2), t1: (u3, u4, u5), t2: (u6, u7, u8)
        teams_users = chain.from_iterable(repeat(t, 3) for t in self.teams)

        # create users profile
        for u in self.users:
            UserProfile.objects.create(user=u, job='job', gender='M', country=country, team=next(teams_users))

        # create 9 challenges: c0, c1, ..., c8
        self.challenges = [
            Challenge.objects.create(name='c{}'.format(i), points=i, category=test_category)
            for i in range(9)
        ]

        # solved challenges: each user u_i solves all challenges from c_0 to c_i (ie: u2 solves c0,c1,c2)
        for i, u in enumerate(self.users, 1):
            for c in self.challenges[:i]:
                ChallengeSolved.objects.create(user=u.profile, challenge=c)


    def test_users_score(self):
        for i, u in enumerate(UserProfile.objects.annotate_score().all(), 1):
            self.assertEqual(u.points, sum(c.points for c in self.challenges[:i]))

    def test_users_score(self):

        for i, u in enumerate(UserProfile.objects.ordered().all(), 1):