Coverage for bundesliga_tippspiel/db/user_generated/LeaderboardEntry.py: 54%

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

49 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 Tuple, List, Dict 

21from jerrycan.base import db 

22from jerrycan.db.ModelMixin import ModelMixin 

23from jerrycan.db.User import User 

24 

25 

26class LeaderboardEntry(ModelMixin, db.Model): 

27 """ 

28 Model that describes the 'leaderboard_entries' SQL table 

29 """ 

30 

31 def __init__(self, *args, **kwargs): 

32 """ 

33 Initializes the Model 

34 :param args: The constructor arguments 

35 :param kwargs: The constructor keyword arguments 

36 """ 

37 super().__init__(*args, **kwargs) 

38 

39 __tablename__ = "leaderboard_entries" 

40 

41 league: int = db.Column(db.String(255), primary_key=True) 

42 season: int = db.Column(db.Integer, primary_key=True) 

43 matchday: int = db.Column(db.Integer, primary_key=True) 

44 user_id: int = db.Column( 

45 db.Integer, 

46 db.ForeignKey("users.id"), 

47 primary_key=True 

48 ) 

49 

50 points: int = db.Column(db.Integer, nullable=False) 

51 position: int = db.Column(db.Integer, nullable=False) 

52 no_bot_position: int = db.Column(db.Integer, nullable=False) 

53 previous_position: int = db.Column(db.Integer, nullable=False) 

54 no_bot_previous_position: int = db.Column(db.Integer, nullable=False) 

55 

56 user: User = db.relationship( 

57 "User", 

58 backref=db.backref("leaderboard_entries", cascade="all, delete") 

59 ) 

60 

61 def get_position_info(self, include_bots: bool) -> Tuple[int, int]: 

62 """ 

63 Retrieves position info 

64 :param include_bots: Whether or not to include bots in the ranking 

65 :return: Current Position, Previous Position 

66 """ 

67 current = self.position if include_bots else self.no_bot_position 

68 previous = self.previous_position \ 

69 if include_bots else self.no_bot_previous_position 

70 return current, previous 

71 

72 def get_tendency(self, include_bots: bool) -> str: 

73 """ 

74 Calculates the position tendency 

75 :param include_bots: Whether or not to include bots 

76 :return: The tendency as a string (example '+2') 

77 """ 

78 current, previous = self.get_position_info(include_bots) 

79 tendency = previous - current 

80 if tendency < 0: 

81 return str(tendency) 

82 elif tendency > 0: 

83 return f"+{tendency}" 

84 else: 

85 return "-" 

86 

87 def get_tendency_class(self, include_bots: bool) -> str: 

88 """ 

89 Calculates the tendency and returns the corrsponding CSS class 

90 :param include_bots: Whether or not to include bots 

91 :return: The tendency CSS class name 

92 """ 

93 current, previous = self.get_position_info(include_bots) 

94 

95 if current < previous: 

96 return "chevron-circle-up" 

97 elif current > previous: 

98 return "chevron-circle-down" 

99 else: 

100 return "minus-circle" 

101 

102 @classmethod 

103 def load_history(cls, league: str, season: int, matchday: int) -> \ 

104 List[Tuple[User, List["LeaderboardEntry"]]]: 

105 """ 

106 Loads the history for the previous matches in a season for each user 

107 :param league: The league for which to retrieve the history 

108 :param season: The season for which to retrieve the history 

109 :param matchday: The matchday for which to retrieve the history 

110 :return: The history as a list of tuples of users and a list of 

111 the corresponding LeaderboardEntry objects. 

112 Sorted by current position 

113 """ 

114 entries: List[LeaderboardEntry] = [ 

115 x for x in 

116 LeaderboardEntry.query.filter_by( 

117 league=league, 

118 season=season 

119 ).options(db.joinedload(LeaderboardEntry.user)).all() 

120 if x.matchday <= matchday 

121 ] 

122 entries.sort(key=lambda x: x.matchday) 122 ↛ exitline 122 didn't run the lambda on line 122

123 

124 history_dict: Dict[int, List[LeaderboardEntry]] = {} 

125 for entry in entries: 125 ↛ 126line 125 didn't jump to line 126, because the loop on line 125 never started

126 if entry.user_id not in history_dict: 

127 history_dict[entry.user_id] = [] 

128 history_dict[entry.user_id].append(entry) 

129 

130 history_list = [ 

131 (history[-1].user, history) 

132 for _, history in history_dict.items() 

133 ] 

134 history_list.sort(key=lambda x: x[1][-1].position) 134 ↛ exitline 134 didn't run the lambda on line 134

135 return history_list