示例#1
0
    def calculate_rating_delta(self, tournament_result, rating_date, tournament, player):
        """
        Determine player delta and tournament properties
        """
        tournament_coefficient = self.tournament_coefficient(tournament)
        tournament_coefficient = get_tournament_coefficient(self.IS_EMA, tournament.id, player, tournament_coefficient)

        base_rank = self.calculate_base_rank(tournament_result, tournament)
        # for ema we had to round base rank
        if self.IS_EMA:
            base_rank = round(base_rank)

        tournament_age = self.tournament_age(tournament.end_date, rating_date)

        delta = tournament_coefficient * base_rank
        delta = self._calculate_percentage(delta, tournament_age)

        return delta, base_rank
示例#2
0
    def calculate_players_rating_rank(self, rating, rating_date, is_last):
        results = []
        two_years_ago = self.get_date(rating_date)

        # it is important to save rating updates time
        rating.updated_on = timezone.now()
        rating.save()

        base_query = self.get_base_query(rating, two_years_ago, rating_date)

        tournament_ids = base_query.values_list('tournament_id',
                                                flat=True).distinct()
        coefficient_temp = TournamentCoefficients.objects.filter(
            tournament_id__in=tournament_ids, rating=rating, date=rating_date)
        coefficients_cache = {}
        coefficients = []
        for coefficient in coefficient_temp:
            coefficients_cache[coefficient.tournament_id] = coefficient

            c = self._calculate_percentage(float(coefficient.coefficient),
                                           coefficient.age)
            coefficients.append(c)

        # TODO: Remove these hardcoded values when tournaments with stages will be implemented
        if not rating.is_online() and AGARI_TOURNAMENT_ID in tournament_ids:
            tournament = Tournament.objects.get(id=AGARI_TOURNAMENT_ID)
            if tournament.end_date >= rating_date:
                age = self.tournament_age(tournament.end_date, rating_date)
                coefficients.append(
                    self._calculate_percentage(AGARI_SECOND_STAGE_COEFFICIENT,
                                               age))
                coefficients.append(
                    self._calculate_percentage(AGARI_FIRST_STAGE_COEFFICIENT,
                                               age))

        coefficients = sorted(coefficients, reverse=True)
        max_coefficient = sum(coefficients[:self.SECOND_PART_MIN_TOURNAMENTS])

        if len(coefficients) < self.SECOND_PART_MIN_TOURNAMENTS:
            max_coefficient += self.SECOND_PART_MIN_TOURNAMENTS - len(
                coefficients)

        for player in self.players:
            first_part_numerator_calculation = []
            first_part_denominator_calculation = []

            second_part_numerator_calculation = []

            # we need to reduce SQL queries with this filter
            deltas = []
            for x in base_query:
                if x.player_id == player.id:
                    deltas.append(x)
            total_tournaments = len(deltas)

            if total_tournaments < self.MIN_TOURNAMENTS_NUMBER:
                continue

            if total_tournaments <= self.FIRST_PART_MIN_TOURNAMENTS:
                tournaments_results = deltas
            else:
                limit = self._determine_tournaments_number(total_tournaments)
                tournaments_results = sorted(deltas,
                                             key=lambda x: x.base_rank,
                                             reverse=True)[:limit]

            if is_last:
                RatingDelta.objects.filter(
                    id__in=[x.id for x in tournaments_results]).update(
                        is_active=True)

            first_part_numerator = 0
            first_part_denominator = 0

            for result in tournaments_results:
                coefficient_obj = coefficients_cache[result.tournament_id]
                coefficient = get_tournament_coefficient(
                    coefficient_obj.tournament_id, player,
                    coefficient_obj.coefficient)

                first_part_numerator += float(result.delta)
                first_part_denominator += float(
                    self._calculate_percentage(float(coefficient),
                                               coefficient_obj.age))

                if is_last:
                    first_part_numerator_calculation.append(
                        '{} * {} * {}'.format(
                            floatformat(result.base_rank, -2),
                            floatformat(coefficient, -2),
                            floatformat(coefficient_obj.age / 100, -2)))

                    first_part_denominator_calculation.append('{} * {}'.format(
                        floatformat(coefficient, -2),
                        floatformat(coefficient_obj.age / 100, -2)))

            if len(tournaments_results) < self.FIRST_PART_MIN_TOURNAMENTS:
                fill_missed_data = self.FIRST_PART_MIN_TOURNAMENTS - len(
                    tournaments_results)
                first_part_denominator += fill_missed_data

                if is_last:
                    for x in range(0, fill_missed_data):
                        first_part_numerator_calculation.append('0')
                        first_part_denominator_calculation.append('1')

            first_part = first_part_numerator / first_part_denominator

            second_part_numerator = 0
            second_part_denominator = max_coefficient

            best_results = sorted(
                deltas, key=lambda x: x.delta,
                reverse=True)[:self.SECOND_PART_MIN_TOURNAMENTS]
            for result in best_results:
                coefficient_obj = coefficients_cache[result.tournament_id]
                coefficient = get_tournament_coefficient(
                    coefficient_obj.tournament_id, player,
                    coefficient_obj.coefficient)

                second_part_numerator += float(result.delta)

                if is_last:
                    second_part_numerator_calculation.append(
                        '{} * {} * {}'.format(
                            floatformat(result.base_rank, -2),
                            floatformat(coefficient, -2),
                            floatformat(coefficient_obj.age / 100, -2)))

            second_part = second_part_numerator / second_part_denominator

            score = self._calculate_percentage(
                first_part,
                self.FIRST_PART_WEIGHT) + self._calculate_percentage(
                    second_part, self.SECOND_PART_WEIGHT)

            rating_calculation = ''
            if is_last:
                first_part_calculation = '({}) / ({})'.format(
                    ' + '.join(first_part_numerator_calculation),
                    ' + '.join(first_part_denominator_calculation))
                second_part_calculation = '({}) / {}'.format(
                    ' + '.join(second_part_numerator_calculation),
                    max_coefficient)
                rating_calculation = '({}) * {} + ({}) * {}'.format(
                    first_part_calculation, self.FIRST_PART_WEIGHT / 100,
                    second_part_calculation, self.SECOND_PART_WEIGHT / 100)

            results.append(
                RatingResult(rating=rating,
                             player=player,
                             score=score,
                             place=0,
                             rating_calculation=rating_calculation,
                             date=rating_date,
                             is_last=is_last))

        place = 1
        results = sorted(results, key=lambda x: x.score, reverse=True)
        for result in results:
            result.place = place
            place += 1

        RatingResult.objects.bulk_create(results)
示例#3
0
 def coefficient_value(self):
     coefficient_obj = self.coefficient_obj
     return get_tournament_coefficient(self.rating.type == Rating.EMA,
                                       self.tournament_id, self.player,
                                       coefficient_obj.coefficient)
示例#4
0
    def _calculate_player_rating(
        self, player, tournaments_results, deltas, coefficients_cache, max_coefficient, selected_coefficients
    ):
        first_part_numerator_calculation = []
        first_part_denominator_calculation = []

        second_part_numerator_calculation = []

        first_part_numerator = 0
        first_part_denominator = 0

        for result in tournaments_results:
            coefficient_obj = coefficients_cache[result.tournament_id]
            coefficient = get_tournament_coefficient(
                self.IS_EMA, coefficient_obj.tournament_id, player, coefficient_obj.coefficient
            )

            first_part_numerator += float(result.delta)
            first_part_denominator += float(self._calculate_percentage(float(coefficient), coefficient_obj.age))

            first_part_numerator_calculation.append(
                "{} * {} * {}".format(
                    floatformat(result.base_rank, -2),
                    floatformat(coefficient, -2),
                    floatformat(coefficient_obj.age / 100, -2),
                )
            )

            first_part_denominator_calculation.append(
                "{} * {}".format(floatformat(coefficient, -2), floatformat(coefficient_obj.age / 100, -2))
            )

        if len(tournaments_results) < self.FIRST_PART_MIN_TOURNAMENTS:
            fill_missed_data = self.FIRST_PART_MIN_TOURNAMENTS - len(tournaments_results)
            first_part_denominator += fill_missed_data

            for _ in range(0, fill_missed_data):
                first_part_numerator_calculation.append("0")
                first_part_denominator_calculation.append("1")

        first_part = first_part_numerator / first_part_denominator

        second_part_numerator = 0
        second_part_denominator = max_coefficient

        best_results = sorted(deltas, key=lambda x: x.delta, reverse=True)[: self.SECOND_PART_MIN_TOURNAMENTS]
        for result in best_results:
            coefficient_obj = coefficients_cache[result.tournament_id]
            coefficient = get_tournament_coefficient(
                self.IS_EMA, coefficient_obj.tournament_id, player, coefficient_obj.coefficient
            )

            second_part_numerator += float(result.delta)

            second_part_numerator_calculation.append(
                "{} * {} * {}".format(
                    floatformat(result.base_rank, -2),
                    floatformat(coefficient, -2),
                    floatformat(coefficient_obj.age / 100, -2),
                )
            )

        second_part = second_part_numerator / second_part_denominator

        score = self._calculate_percentage(first_part, self.FIRST_PART_WEIGHT) + self._calculate_percentage(
            second_part, self.SECOND_PART_WEIGHT
        )

        max_coefficient_calculation = []
        for x in selected_coefficients:
            max_coefficient_calculation.append(
                "{} * {}".format(floatformat(x["coefficient"], -2), floatformat(x["age"] / 100, -2))
            )
        max_coefficient_template = "max_coefficients = ({}) = {}".format(
            " + ".join(max_coefficient_calculation), max_coefficient
        )
        first_part_calculation = "p1 = ({}) / ({}) = {}".format(
            " + ".join(first_part_numerator_calculation), " + ".join(first_part_denominator_calculation), first_part
        )
        second_part_calculation = "p2 = ({}) / max_coefficients = {}".format(
            " + ".join(second_part_numerator_calculation), second_part
        )
        total_calculation = "score = {} * {} + {} * {} = {}".format(
            first_part, self.FIRST_PART_WEIGHT / 100, second_part, self.SECOND_PART_WEIGHT / 100, score
        )
        rating_calculation = "\n\n".join(
            (max_coefficient_template, first_part_calculation, second_part_calculation, total_calculation)
        )

        return rating_calculation, score
示例#5
0
    def _calculate_player_rating(self, player, tournaments_results, deltas, coefficients_cache,
                                 max_coefficient, is_last):
        first_part_numerator_calculation = []
        first_part_denominator_calculation = []

        second_part_numerator_calculation = []

        first_part_numerator = 0
        first_part_denominator = 0

        for result in tournaments_results:
            coefficient_obj = coefficients_cache[result.tournament_id]
            coefficient = get_tournament_coefficient(coefficient_obj.tournament_id, player, coefficient_obj.coefficient)

            first_part_numerator += float(result.delta)
            first_part_denominator += float(self._calculate_percentage(float(coefficient), coefficient_obj.age))

            if is_last:
                first_part_numerator_calculation.append('{} * {} * {}'.format(
                    floatformat(result.base_rank, -2),
                    floatformat(coefficient, -2),
                    floatformat(coefficient_obj.age / 100, -2)
                ))

                first_part_denominator_calculation.append('{} * {}'.format(
                    floatformat(coefficient, -2),
                    floatformat(coefficient_obj.age / 100, -2)
                ))

        if len(tournaments_results) < self.FIRST_PART_MIN_TOURNAMENTS:
            fill_missed_data = self.FIRST_PART_MIN_TOURNAMENTS - len(tournaments_results)
            first_part_denominator += fill_missed_data

            if is_last:
                for x in range(0, fill_missed_data):
                    first_part_numerator_calculation.append('0')
                    first_part_denominator_calculation.append('1')

        first_part = first_part_numerator / first_part_denominator

        second_part_numerator = 0
        second_part_denominator = max_coefficient

        best_results = sorted(deltas, key=lambda x: x.delta, reverse=True)[:self.SECOND_PART_MIN_TOURNAMENTS]
        for result in best_results:
            coefficient_obj = coefficients_cache[result.tournament_id]
            coefficient = get_tournament_coefficient(coefficient_obj.tournament_id, player, coefficient_obj.coefficient)

            second_part_numerator += float(result.delta)

            if is_last:
                second_part_numerator_calculation.append('{} * {} * {}'.format(
                    floatformat(result.base_rank, -2),
                    floatformat(coefficient, -2),
                    floatformat(coefficient_obj.age / 100, -2)
                ))

        second_part = second_part_numerator / second_part_denominator

        score = self._calculate_percentage(first_part, self.FIRST_PART_WEIGHT) + self._calculate_percentage(second_part,
                                                                                                            self.SECOND_PART_WEIGHT)

        rating_calculation = ''
        if is_last:
            first_part_calculation = '({}) / ({})'.format(
                ' + '.join(first_part_numerator_calculation), ' + '.join(first_part_denominator_calculation)
            )
            second_part_calculation = '({}) / {}'.format(
                ' + '.join(second_part_numerator_calculation), max_coefficient
            )
            rating_calculation = '({}) * {} + ({}) * {}'.format(
                first_part_calculation,
                self.FIRST_PART_WEIGHT / 100,
                second_part_calculation,
                self.SECOND_PART_WEIGHT / 100
            )

        return rating_calculation, score
示例#6
0
 def coefficient_value(self):
     coefficient_obj = self.coefficient_obj
     return get_tournament_coefficient(self.tournament_id, self.player,
                                       coefficient_obj.coefficient)