Coverage for bundesliga_tippspiel/utils/collections/Leaderboard.py: 57%

Shortcuts on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

62 statements  

1"""LICENSE 

2Copyright 2017 Hermann Krumrey <hermann@krumreyh.com> 

3 

4This file is part of bundesliga-tippspiel. 

5 

6bundesliga-tippspiel is free software: you can redistribute it and/or modify 

7it under the terms of the GNU General Public License as published by 

8the Free Software Foundation, either version 3 of the License, or 

9(at your option) any later version. 

10 

11bundesliga-tippspiel is distributed in the hope that it will be useful, 

12but WITHOUT ANY WARRANTY; without even the implied warranty of 

13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

14GNU General Public License for more details. 

15 

16You should have received a copy of the GNU General Public License 

17along with bundesliga-tippspiel. If not, see <http://www.gnu.org/licenses/>. 

18LICENSE""" 

19 

20from typing import List, Tuple, Dict 

21from jerrycan.base import db 

22from jerrycan.db.User import User 

23from bundesliga_tippspiel.db import SeasonWinner, LeaderboardEntry, \ 

24 DisplayBotsSettings, MatchdayWinner, UserProfile 

25 

26 

27class Leaderboard: 

28 """ 

29 Class that encapsulates a leaderboard 

30 """ 

31 

32 def __init__( 

33 self, 

34 league: str, 

35 season: int, 

36 matchday: int, 

37 include_bots: bool 

38 ): 

39 """ 

40 Initializes the leaerboard object 

41 :param league: The league of the leaderboard 

42 :param season: The season of the leaderboard 

43 :param matchday: The matchday of the leaderboard 

44 :param include_bots: Whether or not to include bots 

45 """ 

46 self.league = league 

47 self.season = season 

48 self.matchday = matchday 

49 self.include_bots = include_bots 

50 

51 self.season_winners: Dict[int, List[str]] = {} 

52 for season_winner in SeasonWinner.query.filter_by(league=league).all(): 52 ↛ 53line 52 didn't jump to line 53, because the loop on line 52 never started

53 user_id = season_winner.user_id 

54 winner_season = season_winner.season_string 

55 if user_id not in self.season_winners: 

56 self.season_winners[user_id] = [] 

57 self.season_winners[user_id].append(winner_season) 

58 self.matchday_winners: Dict[int, List[int]] = {} 

59 for matchday_winner in MatchdayWinner.query.filter_by( 59 ↛ 62line 59 didn't jump to line 62, because the loop on line 59 never started

60 league=league, season=season 

61 ).all(): 

62 user_id = matchday_winner.user_id 

63 winner_matchday = matchday_winner.matchday 

64 if user_id not in self.matchday_winners: 

65 self.matchday_winners[user_id] = [] 

66 self.matchday_winners[user_id].append(winner_matchday) 

67 

68 self.ranking: List[LeaderboardEntry] = \ 

69 LeaderboardEntry.query.filter_by( 

70 league=league, 

71 season=season, 

72 matchday=matchday 

73 ).options(db.joinedload(LeaderboardEntry.user) 

74 .subqueryload(User.profile) 

75 .subqueryload(UserProfile.favourite_team)).all() 

76 self.ranking.sort(key=lambda x: x.position) 76 ↛ exitline 76 didn't run the lambda on line 76

77 self.history: List[Tuple[User, List["LeaderboardEntry"]]] \ 

78 = LeaderboardEntry.load_history(league, season, matchday) 

79 

80 if not include_bots: 80 ↛ exitline 80 didn't return from function '__init__', because the condition on line 80 was never false

81 self.ranking = [ 

82 x for x in self.ranking 

83 if DisplayBotsSettings.bot_symbol() not in x.user.username 

84 ] 

85 self.history = [ 

86 x for x in self.history 

87 if DisplayBotsSettings.bot_symbol() not in x[0].username 

88 ] 

89 

90 def ranking_to_table_data(self) -> List[Tuple[ 

91 int, str, str, User, List[str], List[int], int 

92 ]]: 

93 """ 

94 Converts the leaderboard into a format that can easily be entered 

95 into a HTML table 

96 :return: The data as tuple with the following attributes: 

97 - position 

98 - tendency (example: +2 or -3 etc.) 

99 - tendency-class 

100 - user 

101 - previous season wins 

102 - previous matchday wins 

103 - points 

104 """ 

105 table_data = [] 

106 for item in self.ranking: 106 ↛ 107line 106 didn't jump to line 107, because the loop on line 106 never started

107 table_data.append(( 

108 item.get_position_info(self.include_bots)[0], 

109 item.get_tendency(self.include_bots), 

110 item.get_tendency_class(self.include_bots), 

111 item.user, 

112 self.season_winners.get(item.user_id, []), 

113 self.matchday_winners.get(item.user_id, []), 

114 item.points 

115 )) 

116 return table_data 

117 

118 def matchday_ranking_to_table_data(self) -> List[Tuple[ 

119 int, None, None, User, List[str], List[int], int 

120 ]]: 

121 """ 

122 Calculates the leaderboard ranking to table data for the current 

123 matchday only 

124 :return: The data as tuple with the following attributes: 

125 - position 

126 - tendency (None in this case) 

127 - tendency-class (None in this case) 

128 - user 

129 - previous season wins (Empty list in this case) 

130 - The matchday wins for the current mtchday only 

131 - points on this matchday 

132 """ 

133 table_data: List[Tuple[User, List[int], int]] = [] 

134 matchday_winners = [ 

135 user_id for user_id, matchdays in self.matchday_winners.items() 

136 if self.matchday in matchdays 

137 ] 

138 

139 user_histories = dict(self.history) 

140 for item in self.ranking: 140 ↛ 141line 140 didn't jump to line 141, because the loop on line 140 never started

141 points = item.points 

142 if item.matchday > 1: 

143 previous = user_histories[item.user][-2] 

144 points -= previous.points 

145 

146 table_data.append(( 

147 item.user, 

148 [self.matchday] if item.user_id in matchday_winners else [], 

149 points 

150 )) 

151 table_data.sort(key=lambda x: x[2], reverse=True) 151 ↛ exitline 151 didn't run the lambda on line 151

152 table: List[Tuple[int, None, None, User, List[str], List[int], int]] \ 

153 = [] 

154 

155 for i, data in enumerate(table_data): 155 ↛ 156line 155 didn't jump to line 156, because the loop on line 155 never started

156 empty: List[str] = [] 

157 table.append(( 

158 i + 1, 

159 None, 

160 None, 

161 data[0], 

162 empty, 

163 data[1], 

164 data[2] 

165 )) 

166 return table 

167 

168 def history_to_chart_data(self) -> List[Tuple[str, str, List[int]]]: 

169 """ 

170 Creates data for the ranking chart 

171 :return: The data to be used by the javascript chart 

172 """ 

173 chart_colours = ["red", "blue", "yellow", 

174 "green", "purple", "orange", 

175 "brown", "black", "gray"] 

176 

177 chart_data = [] 

178 

179 for i, (user, user_history) in enumerate(self.history): 179 ↛ 180line 179 didn't jump to line 180, because the loop on line 179 never started

180 chart_colour = chart_colours[i % len(chart_colours)] 

181 user_positions = [] 

182 for item in user_history: 

183 position = item.get_position_info(self.include_bots)[0] 

184 user_positions.append(position) 

185 chart_data.append((user.username, chart_colour, user_positions)) 

186 

187 return chart_data