def _get_winning_percentage(player_name): """Populates ranking entity based on players winning %""" user = User.query(User.name == player_name).get() if user: total_win = float( len( Score.query(Score.user == user.key, Score.result == 'win').fetch())) total_lose = float( len( Score.query(Score.user == user.key, Score.result == 'lose').fetch())) total_tie = float( len( Score.query(Score.user == user.key, Score.result == 'tie').fetch())) # tie counts for 1/2 win and 1/2 lose winning_per = ((total_win + (total_tie / 2)) / (total_win + total_lose + total_tie)) # logging.info(total_win) # logging.info(total_lose) # logging.info(total_tie) # logging.info(winning_per) ranking = Ranking.query(Ranking.user == user.key).get() if ranking: ranking.winning_percent = winning_per ranking.put() else: ranking = Ranking(user=user.key, winning_percent=winning_per) ranking.put()
def get_user_ranking(self, request): """Returns the performance of the player as a Ranking.""" user = User.query(User.name == request.user_name).get() if not user: raise endpoints.NotFoundException( 'A User with that name does not exist!') scores = Score.query(Score.user == user.key).fetch() if not scores: raise endpoints.NotFoundException( 'No scores were found for that user!') wins = sum(s.won == True for s in scores) percent_won = (float(wins)/len(scores)) * 100 number_of_guesses = sum(score.total_incorrect for score in scores) avg_wrong = float(number_of_guesses)/len(scores) ranking = Ranking.query(Ranking.user == user.key).get() if ranking: ranking.wins = wins ranking.percent_won = percent_won ranking.avg_wrong = avg_wrong ranking.put() return ranking.to_form("Ranking has been updated for {}".format( user.name)) else: ranking = Ranking.new_ranking(user=user.key, wins=wins, percent_won=percent_won, avg_wrong=avg_wrong) return ranking.to_form("Ranking created for {}".format(user.name))
def rank_them(users, number_of_results): rankings = [] for user in users: scores = Score.query(ancestor=user.key) wins = losses = cats = moves = 0.0 for score in scores: # chore: might not want to include moves in losses in the # rankings algorithm moves += score.moves if score.won: wins += 1.0 elif score.cats: cats += 1.0 else: losses += 1.0 games = wins + cats + losses # don't rank users who haven't finished a game if games != 0: rating = Ranking(user=user.name, win_percent=wins / games, cats_percent=cats / games, avg_moves=moves / games) rankings.append(rating) # sorts are stable(order from initial sort retained unless changed # by a later sort) so execute the last sort criteria first rankings = sorted(rankings, key=attrgetter('avg_moves')) rankings = sorted(rankings, key=attrgetter('win_percent', 'cats_percent'), reverse=True) if number_of_results: rankings = rankings[:number_of_results] return rankings
def rankings_handler(self, request): rankings = Ranking.query() rankings = rankings.order(-Ranking.ranking) return Ranking_forms( items=[copy_ranking_from_list_to_form(rank) \ for rank in rankings] )
def load_rankings(cls, table, matches, has_hs=True): """has_hs=False is necessary for rly old data""" try: event_key = matches[0][0].event_key except IndexError: logging.warning("can't load rankings on zero length match table!") return high_scores, wlt = cls.highscores_wlt(matches) ret = [] #first = True for tr in table.find_all("tr"): td_tags = list(tr.find_all("td")) if not td_tags: continue td = [td.get_text() for td in td_tags] tkey = "ftc" + td[1] twlt = wlt[tkey] if not has_hs: r = Ranking(event_key=event_key, team_key=tkey, rank=int(td[0]), qp_rp=int(td[3]), rp_tbp=int(td[4]), high_score=high_scores.get(tkey, 0), wins=twlt[0], losses=twlt[1], ties=twlt[2], dqed=0, played=int(td[5])) else: r = Ranking(event_key=event_key, team_key=tkey, rank=int(td[0]), qp_rp=int(td[3]), rp_tbp=int(td[4]), high_score=int(td[5]), wins=twlt[0], losses=twlt[1], ties=twlt[2], dqed=0, played=int(td[6])) ret.append(r) return ret
async def generate_rankings(cls, event_key): match_data = await cls.get_match_data(where="m.event_key=$1", params=[event_key], use_dict=False) rankings = {} red: MatchScore blue: MatchScore match: Match for match, red, blue in match_data: for team in red.teams + blue.teams: if team not in rankings: rankings[team] = Ranking(event_key=event_key, team_key=team, qp_rp=0, rp_tbp=0, high_score=0, wins=0, losses=0, ties=0, played=0, dqed=0) if match.winner == 'tie': for team in red.teams + blue.teams: if team in red.surrogates or team in blue.surrogates: continue rankings[team].played += 1 rankings[team].ties += 1 rankings[team].qp_rp += 1 rankings[team].rp_tbp += min(red.total - red.penalty, blue.total - blue.penalty) continue elif match.winner == 'red': winner = red loser = blue elif match.winner == 'blue': winner = blue loser = red else: raise ValueError( f"{match.winner} is invalid value for match.winner!") for team in winner.teams: if team in winner.surrogates: continue rankings[team].played += 1 rankings[team].wins += 1 rankings[team].qp_rp += 2 rankings[team].rp_tbp += loser.total - loser.penalty for team in loser.teams: if team in loser.surrogates: continue rankings[team].played += 1 rankings[team].losses += 1 rankings[team].rp_tbp += loser.total await asyncio.gather(*[r.upsert() for r in rankings.values()]) await Ranking.update_ranks(event_key)
def check_if_user_exists(self, user): # Check if current user is already registered in datastore User table. user_id = self.get_user_id(user) u_key = ndb.Key(User, user_id) user_profile = u_key.get() # If user is not registered, register it. if not user_profile: user_profile = User(key=u_key, name=user.nickname(), email=user.email()) user_profile.put() user_ranking = Ranking(user=u_key, total_moves=0, guessed_moves=0, ranking=0) user_ranking.put() return copy_user_profile_to_form(user_profile)
def get_users_wins(self, request): """Returns all wins of a player + prepares the ranking""" player = Player.query(Player.name == request.user_name).get() if not player: raise endpoints.NotFoundException( 'A User with that name does not exist!') rankings = Ranking.query().fetch() members_in_ranking = [] for ranking in rankings: members_in_ranking.append(ranking.player) if player.name in members_in_ranking: scores = Score.query(Score.player == player.key).count() players_positons = Ranking.query(Ranking.player == player.name).get() players_positons.number_of_wins = scores players_positons.put() return StringMessage(message="wins: {} by player:{}".format(scores, player.name)) else: scores = Score.query(Score.player == player.key).count() get_ranked = Ranking.new_in_ranking(player.name, scores) return StringMessage(message="wins: {} by {}".format(scores, player.name))
def get_ranking(self, event="10K", sex="M", year="2014", age_group="ALL"): r = requests.get("http://www.thepowerof10.info/rankings/rankinglist.aspx", params={"event": event, "agegroup": age_group, "sex": sex, "year": 2014}) soup = BeautifulSoup(r.content) rankings_table = soup.find(id="ctl00_cphBody_lblCachedRankingList").find_all('table')[0] ranking_rows = [row for row in rankings_table.find_all("tr") if row["class"][0] not in ["rankinglisttitle", "rankinglistheadings", "rankinglistsubheader"]] rankings = [] for row in ranking_rows: if row.find_all("td")[0].string is None: continue r = Ranking({"athlete": Athlete(), "event": event, "year": year, "age_group": age_group}) r.rank = int(row.find_all("td")[0].string) r.time = row.find_all("td")[1].string r.athlete.name = row.find_all("td")[6].string.encode("utf-8") r.athlete.id = int(row.find_all("td")[6].a["href"].split("=")[1]) r.venue = row.find_all("td")[11].string r.date = row.find_all("td")[12].string rankings.append(r) return rankings
def get_users_wins(self, request): """Returns all wins of a player + prepares the ranking""" player = Player.query(Player.name == request.user_name).get() if not player: raise endpoints.NotFoundException( 'A User with that name does not exist!') rankings = Ranking.query().fetch() members_in_ranking = [] for ranking in rankings: members_in_ranking.append(ranking.player) if player.name in members_in_ranking: scores = Score.query(Score.player == player.key).count() players_positons = Ranking.query( Ranking.player == player.name).get() players_positons.number_of_wins = scores players_positons.put() return StringMessage(message="wins: {} by player:{}".format( scores, player.name)) else: scores = Score.query(Score.player == player.key).count() get_ranked = Ranking.new_in_ranking(player.name, scores) return StringMessage( message="wins: {} by {}".format(scores, player.name))
def update_rank(event, context): with application.app_context(): my_kwargs = event.get("kwargs") date = datetime.datetime.utcnow().strftime('%Y/%m/%d') for i in range(my_kwargs["start"], my_kwargs["end"]): url = "https://www.acmicpc.net/ranklist/" + str(i) soup = get_soup_from_url(url) table = soup.find(id='ranklist') trs = table.tbody.find_all('tr') boj_ids = list() boj_ranks = list() for tr in trs: tds = tr.find_all('td') if int(tds[3].a.string.strip()) <= 19: break boj_ids.append(''.join(tds[1].find_all(text=True, recursive=True)).strip()) boj_ranks.append(int(tds[0].string)) api = request_koo_api("user", boj_ids) koo_ranks = list(user["ranking"] for user in api) for _ in range(len(boj_ids)): boj_id = boj_ids[_] boj_rank = boj_ranks[_] if koo_ranks[_] == None: koo_rank = 0 else: koo_rank = koo_ranks[_] + 1 data = {date: [boj_rank, koo_rank]} if not Ranking.query.filter_by(boj_id=boj_id).scalar(): ranking = Ranking(boj_id=boj_id, ranking=data) db.session.add(ranking) db.session.commit() else: user = Ranking.query.filter_by(boj_id=boj_id) new_ranking = user.first().ranking new_ranking.update(data) user.first().ranking = new_ranking db.session.commit() print("{0} {1} {2}".format(boj_id, boj_rank, koo_rank)) return "OK"
def load_rankings(cls, data, matches, event_key): # since ftcscores has basically everything we need, we just load it right in! _, wlt = ResultsPageHelper.highscores_wlt(matches) rankings = [] for r in data['rankings']: c = r['current'] tkey = f"ftc{r['number']}" twlt = wlt[tkey] ranking = Ranking(event_key=event_key, team_key=tkey, rank=r['rank'], qp_rp=c['qp'], rp_tbp=c['rp'], high_score=c['highest'], wins=twlt[0], losses=twlt[1], ties=twlt[2], dqed=0, played=c['matches']) rankings.append(ranking) return rankings
def move_handler(self, request): # Check for current user. user = endpoints.get_current_user() if not user: raise endpoints.UnexpectedException('Authentication required!') # Get game web safe key. web_safe_key = request.web_safe_key # Get key for cards moved. move_one = request.move_one move_two = request.move_two # If no card as been turned, raise exception. if move_one is None and move_two is None: raise endpoints.UnauthorizedException('No move has been made!') # Get game key using web safe key. game_key = ndb.Key(urlsafe=request.web_safe_key) if not game_key: raise endpoints.UnauthorizedException('Game is not available!') # Fetch game. game = game_key.get() if not game: raise endpoints.NotFoundException('Game not found') if game.complete: raise endpoints.UnauthorizedException('This game is already finished!') sequence = game.sequence tiles_found = game.tiles_found score = game.score move_record = game.move_record # If car as been already guessed, alert user. if (move_one is not None and tiles_found[move_one] >= 0) or \ (move_two is not None and tiles_found[move_two] >= 0): raise endpoints.UnauthorizedException('Figure already found') # If move one and two correspond to the same card, its an illegal move. # Alert user. if (move_one == move_two): raise endpoints.UnauthorizedException('Illegal move') # -1 stands for None because has to be Integer, not Boolean move_one_key = -1 move_two_key = -1 # Get figures from sequence list corresponding to turned card. if move_one is not None: move_one_key = sequence[move_one] if move_two is not None: move_two_key = sequence[move_two] guessed = False # Run if two carsd were turned. if move_one_key != -1 and move_two_key != -1: complete = None # Get user key u_key = ndb.Key(User, user.email()) # Fetch user ranking. rankings = Ranking.query() rankings = rankings.filter(Ranking.user == u_key) rankings = rankings.fetch(1) ranking = rankings[0] # Update user ranking. ranking.total_moves = ranking.total_moves + 1 # Run if user guessed. if move_one_key == move_two_key: guessed = True score = score + 3 tiles_found[move_one] = move_one_key tiles_found[move_two] = move_two_key game.tiles_found = tiles_found complete = True # Check if game is over. for t in tiles_found: if t == -1: complete = False break game.complete = complete ranking.guessed_moves = ranking.guessed_moves + 1 else: score = score - 1 if score < 0: score = 0 # Update game data. move_record.append(move_one) move_record.append(move_two) game.move_record = move_record game.score = score game.put() # Update ranking data. ranking.ranking = float(ranking.guessed_moves) / ranking.total_moves ranking.put() # update score data table if games is complete. if complete: score = Score( user=u_key, score=score, total_moves=len(move_record) / 2 ) score.put() # Return move info. return copy_move_result_to_form(game, move_one_key, move_two_key, guessed)
def get_user_rankings(self, request): """Returns Players in descending order. The one with most wins is on the top""" rankings = Ranking.query().order(-Ranking.number_of_wins).fetch() return RankingForms(items=[ranking.to_form() for ranking in rankings])
async def calc_rankings(cls, matches, team_keys: set): # the correct way to do this would be to use a minPQ best_ten = {k: [] for k in team_keys} for m, red, blue in matches: if team_keys.isdisjoint(red.teams) and team_keys.isdisjoint( blue.teams): continue if m.winner == "tie": mi = cls.MatchItem(qp_rp=1, score=red.total, match_tuple=(m, red, blue), rp_tbp=min(red.total - red.penalty, blue.total - blue.penalty)) for team in red.teams + blue.teams: if team in red.surrogates or team in blue.surrogates: continue if team in team_keys: enqueue(mi, best_ten[team]) continue elif m.winner == "red": winner, loser = red, blue elif m.winner == "blue": winner, loser = blue, red else: raise ValueError( f"match.winner for {m.key} is not in {{'red', 'blue', 'tie'}}" ) for team in winner.teams: if team in winner.surrogates: continue mi = cls.MatchItem(qp_rp=2, score=winner.total, match_tuple=(m, red, blue), rp_tbp=loser.total - loser.penalty) print(team, repr(mi)) if team in team_keys: enqueue(mi, best_ten[team]) for team in loser.teams: if team in loser.surrogates: continue mi = cls.MatchItem(qp_rp=0, score=loser.total, match_tuple=(m, red, blue), rp_tbp=loser.total - loser.penalty) print(team, repr(mi)) if team in team_keys: enqueue(mi, best_ten[team]) ret = [] import pprint pprint.pprint(best_ten) for team, match_item in best_ten.items(): ret.append( Ranking( team_key=team, qp_rp=sum(a.qp_rp for a in match_item), rp_tbp=sum(a.rp_tbp for a in match_item), high_score=max(a.score for a in match_item), wins=len([2 for a in match_item if a.qp_rp == 2]), losses=len([0 for a in match_item if a.qp_rp == 0]), ties=len([0 for a in match_item if a.qp_rp == 1]), played=len(match_item), dqed=0, )) return ret
def get_user_rankings(self, request): """Return all ranking sort by winning percent""" return RankForms(items=[ rank.to_form() for rank in Ranking.query().order(-Ranking.winning_percent) ])