def populate_historical_ratings(self): pairings_that_should_have_ratings = PlayerPairing.objects.exclude(game_link='', result='').exclude(white=None, black=None).nocache() pairings_that_need_ratings = pairings_that_should_have_ratings.filter(white_rating=None) | pairings_that_should_have_ratings.filter(black_rating=None) api_poll_count = 0 for p in pairings_that_need_ratings.exclude(game_link=''): # Poll ratings for the game from the lichess API if p.game_id() is None: continue p.refresh_from_db() game_meta = lichessapi.get_game_meta(p.game_id(), priority=0, timeout=300) p.white_rating = game_meta['players']['white']['rating'] p.black_rating = game_meta['players']['black']['rating'] p.save(update_fields=['white_rating', 'black_rating']) api_poll_count += 1 if api_poll_count >= 100: # Limit the processing per task execution return for p in pairings_that_need_ratings.filter(game_link=''): round_ = p.get_round() if round_ is None: continue season = round_.season league = season.league p.refresh_from_db() if not round_.is_completed: p.white_rating = p.white.rating_for(league) p.black_rating = p.black.rating_for(league) else: # Look for ratings from a close time period p.white_rating = _find_closest_rating(p.white, round_.end_date, season) p.black_rating = _find_closest_rating(p.black, round_.end_date, season) p.save(update_fields=['white_rating', 'black_rating']) for b in PlayerBye.objects.filter(player_rating=None, round__publish_pairings=True).nocache(): b.refresh_from_db() if not b.round.is_completed: b.player_rating = b.player.rating_for(b.round.season.league) else: b.player_rating = _find_closest_rating(b.player, b.round.end_date, b.round.season) b.save(update_fields=['player_rating']) for tm in TeamMember.objects.filter(player_rating=None, team__season__is_completed=True).nocache(): tm.refresh_from_db() tm.player_rating = _find_closest_rating(tm.player, tm.team.season.end_date(), tm.team.season) tm.save(update_fields=['player_rating']) for alt in Alternate.objects.filter(player_rating=None, season_player__season__is_completed=True).nocache(): alt.refresh_from_db() alt.player_rating = _find_closest_rating(alt.season_player.player, alt.season_player.season.end_date(), alt.season_player.season) alt.save(update_fields=['player_rating']) for sp in SeasonPlayer.objects.filter(final_rating=None, season__is_completed=True).nocache(): sp.refresh_from_db() sp.final_rating = _find_closest_rating(sp.player, sp.season.end_date(), sp.season) sp.save(update_fields=['final_rating'])
def update_tv_state(self): games_to_update = PlayerPairing.objects.filter(result='', tv_state='default').exclude(game_link='').nocache() for game in games_to_update: gameid = get_gameid_from_gamelink(game.game_link) if gameid is not None: try: meta = lichessapi.get_game_meta(gameid, priority=1) if 'status' not in meta or meta['status'] != 'started': game.tv_state = 'hide' game.save() except Exception as e: logger.warning('Error updating tv state for %s: %s' % (game.game_link, e))
def _find_closest_rating(player, date, season): if player is None: return None if season.league.competitor_type == 'team': season_pairings = TeamPlayerPairing.objects.filter( team_pairing__round__season=season).exclude( white_rating=None, black_rating=None).nocache() else: season_pairings = LonePlayerPairing.objects.filter( round__season=season).exclude(white_rating=None, black_rating=None).nocache() pairings = season_pairings.filter(white=player) | season_pairings.filter( black=player) def pairing_date(p): if season.league.competitor_type == 'team': return p.team_pairing.round.end_date else: return p.round.end_date def rating(p): if p.white == player: return p.white_rating else: return p.black_rating pairings_by_date = sorted([(pairing_date(p), p) for p in pairings]) if len(pairings_by_date) == 0: # Try to find the seed rating sp = SeasonPlayer.objects.filter(season=season, player=player).first() if sp is not None and sp.seed_rating is not None: return sp.seed_rating # Default to current rating return player.rating_for(season.league) pairings_by_date_lt = [p for p in pairings_by_date if p[0] <= date] pairings_by_date_gt = [p for p in pairings_by_date if p[0] > date] if len(pairings_by_date_lt) > 0: # Get the rating AFTER the game p = pairings_by_date_lt[-1][1] if p.game_id() is not None: game_meta = lichessapi.get_game_meta(p.game_id(), priority=0, timeout=300) player_meta = game_meta['players'][ 'white'] if p.white == player else game_meta['players']['black'] if 'ratingDiff' in player_meta: return player_meta['rating'] + player_meta['ratingDiff'] return rating(p) else: return rating(pairings_by_date_gt[0][1])
def update_tv_state(self): games_starting = PlayerPairing.objects.filter( result='', game_link='', scheduled_time__lt=timezone.now()).nocache() games_starting = games_starting.filter(loneplayerpairing__round__end_date__gt=timezone.now()) | \ games_starting.filter( teamplayerpairing__team_pairing__round__end_date__gt=timezone.now()) games_in_progress = PlayerPairing.objects.filter( result='', tv_state='default').exclude(game_link='').nocache() for game in games_starting: try: league = game.get_round().season.league for meta in lichessapi.get_latest_game_metas( game.white.lichess_username, 5, priority=1, timeout=300): try: if meta['players']['white']['user'][ 'id'].lower() == game.white.lichess_username.lower() and \ meta['players']['black']['user'][ 'id'].lower() == game.black.lichess_username.lower() and \ meta['clock']['initial'] == league.time_control_initial() and \ meta['clock']['increment'] == league.time_control_increment() and \ meta['rated'] == True: game.game_link = get_gamelink_from_gameid(meta['id']) game.save() except KeyError: pass except Exception as e: logger.warning('Error updating tv state for %s: %s' % (game, e)) for game in games_in_progress: gameid = get_gameid_from_gamelink(game.game_link) if gameid is not None: try: meta = lichessapi.get_game_meta(gameid, priority=1, timeout=300) if 'status' not in meta or meta['status'] != 'started': game.tv_state = 'hide' if 'status' in meta and meta['status'] == 'draw': game.result = '1/2-1/2' elif 'winner' in meta and meta[ 'status'] != 'timeout': # timeout = claim victory (which isn't allowed) if meta['winner'] == 'white': game.result = '1-0' elif meta['winner'] == 'black': game.result = '0-1' game.save() except Exception as e: logger.warning('Error updating tv state for %s: %s' % (game.game_link, e))