-
Notifications
You must be signed in to change notification settings - Fork 8
/
rating_calculate.py
120 lines (90 loc) · 4.51 KB
/
rating_calculate.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import datetime
from django.core.management.base import BaseCommand
from django.db import transaction
from django.db.models import Q
from django.utils import timezone
from rating.calculation.crr import RatingCRRCalculation
from rating.calculation.online import RatingOnlineCalculation
from rating.calculation.rr import RatingRRCalculation
from rating.models import Rating, RatingDelta, RatingResult
from tournament.models import Tournament
def get_date_string():
return timezone.now().strftime('%H:%M:%S')
class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument('rating_type', type=str)
def handle(self, *args, **options):
print('{0}: Start'.format(get_date_string()))
rating_type = options['rating_type']
rating = None
tournaments = None
calculator = None
rating_date = None
today = datetime.datetime.now().date()
if rating_type == 'rr':
rating_date = today - datetime.timedelta(days=365 * 2)
calculator = RatingRRCalculation()
rating = Rating.objects.get(type=Rating.RR)
tournaments = Tournament.public.filter(
Q(tournament_type=Tournament.RR) |
Q(tournament_type=Tournament.EMA) |
Q(tournament_type=Tournament.FOREIGN_EMA)
).filter(is_upcoming=False).order_by('end_date')
if rating_type == 'crr':
rating_date = today - datetime.timedelta(days=365 * 2)
calculator = RatingCRRCalculation()
rating = Rating.objects.get(type=Rating.CRR)
tournaments = Tournament.public.filter(
Q(tournament_type=Tournament.CRR) |
Q(tournament_type=Tournament.RR) |
Q(tournament_type=Tournament.EMA) |
Q(tournament_type=Tournament.FOREIGN_EMA)
).filter(is_upcoming=False).order_by('end_date')
if rating_type == 'online':
rating_date = today - datetime.timedelta(days=913)
calculator = RatingOnlineCalculation()
rating = Rating.objects.get(type=Rating.ONLINE)
tournaments = (Tournament.public
.filter(tournament_type=Tournament.ONLINE)
.filter(is_upcoming=False)
.order_by('end_date'))
if not rating:
print('Unknown rating type: {}'.format(rating_type))
return
print('Calculating dates...')
continue_work = True
with transaction.atomic():
RatingResult.objects.filter(rating=rating).delete()
RatingDelta.objects.filter(rating=rating).delete()
tournaments_diff = {}
dates_to_process = []
while continue_work:
need_to_recalculate = False
if rating_date > today:
continue_work = False
# we need to rebuild rating only after changes in tournaments
# there is no need to rebuild it each day
limited_tournaments = tournaments.filter(end_date__lte=rating_date)
for tournament in limited_tournaments:
if tournament.id not in tournaments_diff:
# new tournament was added
need_to_recalculate = True
tournaments_diff[tournament.id] = 100
else:
# old tournament changed age weight
age = calculator.tournament_age(tournament.end_date, rating_date)
if tournaments_diff[tournament.id] != age:
need_to_recalculate = True
tournaments_diff[tournament.id] = age
if need_to_recalculate:
dates_to_process.append(rating_date)
rating_date = rating_date + datetime.timedelta(days=1)
print('Dates to process: {}'.format(len(dates_to_process)))
for i, rating_date in enumerate(dates_to_process):
is_last = i == len(dates_to_process) - 1
limited_tournaments = tournaments.filter(end_date__lte=rating_date)
print(rating_date, limited_tournaments.count(), is_last)
for tournament in limited_tournaments:
calculator.calculate_players_deltas(tournament, rating, rating_date, is_last)
calculator.calculate_players_rating_rank(rating, rating_date, is_last)
print('{0}: End'.format(get_date_string()))