Coverage for src/mathenjeu/activities/base_classes.py: 66%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

103 statements  

1# -*- coding: utf-8 -*- 

2""" 

3@file 

4@brief Base classes. 

5""" 

6 

7 

8class Base: 

9 """ 

10 Base class. 

11 """ 

12 

13 def __init__(self, eid, name): 

14 """ 

15 @param eid entity id 

16 @param name unique name (mostly for logging) 

17 """ 

18 self._col_eid = eid 

19 self._col_name = name 

20 

21 @property 

22 def Id(self): 

23 """ 

24 Returns the identifier. 

25 """ 

26 return self._col_eid 

27 

28 @property 

29 def Fields(self): 

30 """ 

31 Returns all the fields. 

32 """ 

33 return list(sorted(k for k in self.__dict__ if k.startswith("_col"))) 

34 

35 def to_dict(self): 

36 """ 

37 Returns all values as a dictionary. 

38 """ 

39 return {k: getattr(self, k) for k in self.__dict__ if k.startswith("_col")} 

40 

41 @staticmethod 

42 def _format_value(v): 

43 if isinstance(v, str): 

44 return "'{0}'".format(v.replace("\\", "\\\\").replace("'", "\\'")) 

45 if isinstance(v, list): 

46 rs = [repr(_) for _ in v] 

47 return '[{0}]'.format(', '.join(rs)) 

48 return repr(v) 

49 

50 def __repr__(self): 

51 """ 

52 Usual 

53 """ 

54 name = self.__class__.__name__ 

55 fields = self.Fields 

56 pars = ["{0}={1}".format(k, Base._format_value( 

57 getattr(self, k))) for k in fields] 

58 text = "{0}({1})".format(name, ", ".join(pars)) 

59 return text 

60 

61 def __getitem__(self, field): 

62 """ 

63 Returns the value associated to a field. 

64 

65 @param field field 

66 @return value 

67 """ 

68 key = "_col_" + field 

69 if not hasattr(self, key): 

70 raise ValueError("Unable to find attribute '{0}'.".format(field)) 

71 return getattr(self, key) 

72 

73 

74class Display(Base): 

75 """ 

76 Defines how an activity should be displayed. 

77 """ 

78 

79 def __init__(self, eid, name): 

80 """ 

81 @param eid unique identifier 

82 @param name name 

83 """ 

84 Base.__init__(self, eid, name) 

85 

86 

87class LanguageBase(Base): 

88 """ 

89 Base class for language specific content. 

90 """ 

91 

92 def __init__(self, eid, name, lang): 

93 """ 

94 @param eid entity id 

95 @param name unique name (mostly for logging) 

96 @param lang language 

97 """ 

98 Base.__init__(self, eid, name) 

99 self._col_lang = lang 

100 

101 

102class Notion(LanguageBase): 

103 """ 

104 Defines what an activity intents to introduce. 

105 """ 

106 

107 def __init__(self, eid, name, lang, domain=None, level=None, depends=None, 

108 content=None): 

109 """ 

110 @param eid identifier 

111 @param name unique name 

112 @param domain domain (maths, ...) 

113 @param lang language 

114 @param level level, grade... 

115 @param depends is there any needed notion to know before knowing this one?, 

116 should be a list of @see cl Notion. 

117 @param content data 

118 """ 

119 if depends is not None and not isinstance(depends, list): 

120 depends = [depends] 

121 LanguageBase.__init__(self, eid, name, lang) 

122 self._col_domain = domain 

123 self._col_level = level 

124 self._col_depends = depends 

125 self._col_content = content 

126 

127 

128class Activity(LanguageBase): 

129 """ 

130 Defines an activity, a question, a game... 

131 """ 

132 

133 def __init__(self, eid, name, lang, title, notion=None, 

134 description=None, content=None): 

135 """ 

136 @param eid identifier 

137 @param name unique name 

138 @param lang language 

139 @param title display name 

140 @param notion notion (@see cl Notion) 

141 @param description description 

142 @param content content 

143 """ 

144 LanguageBase.__init__(self, eid, name, lang) 

145 self._col_title = title 

146 self._col_notion = notion 

147 self._col_description = description 

148 self._col_content = content 

149 

150 

151class ActivityGroup(Base): 

152 """ 

153 Defines a set of activities. 

154 """ 

155 

156 def __init__(self, eid, name, acts=None): 

157 """ 

158 @param eid identifier 

159 @param name unique name 

160 @param acts set of activities 

161 """ 

162 Base.__init__(self, eid, name) 

163 if acts is None: 

164 self._col_acts = [] 

165 elif isinstance(acts, list): 

166 self._col_acts = acts 

167 else: 

168 raise TypeError("Activities must be defined as a list.") 

169 

170 def __len__(self): 

171 """ 

172 Returns the number of activities. 

173 """ 

174 return len(self._col_acts) 

175 

176 def __iter__(self): 

177 """ 

178 To iterate on activities. 

179 """ 

180 return self._col_acts.__iter__() 

181 

182 def __getitem__(self, item): 

183 """ 

184 Retrieves the question. 

185 

186 @param item item 

187 @return @see cl Activity 

188 """ 

189 if not isinstance(item, int): 

190 try: 

191 ii = int(item) 

192 except ValueError: 

193 raise ValueError( # pylint: disable=W0707 

194 "Unable to retrieve question '{0}'.".format(item)) 

195 else: 

196 ii = item 

197 

198 return self._col_acts[ii] 

199 

200 def get_previous(self, current): 

201 """ 

202 Computes the previous question or returns None 

203 if does not exist. 

204 

205 @param current previous question 

206 @return next question or None 

207 """ 

208 try: 

209 r = int(current) 

210 except ValueError: 

211 r = len(self) 

212 return (r - 1) if r > 0 else None 

213 

214 def get_next(self, current): 

215 """ 

216 Computes the next question or returns None 

217 if does not exist. 

218 

219 @param current current question 

220 @return next question or None 

221 """ 

222 try: 

223 r = int(current) 

224 except ValueError: 

225 r = len(self) 

226 return (r + 1) if r < len(self) - 1 else None 

227 

228 def get_display_item(self, item): 

229 """ 

230 Returns a displayable number. 

231 

232 @param item item number 

233 @return string 

234 """ 

235 if isinstance(item, int): 

236 return str(item + 1) # items starts at 0 

237 if isinstance(item, str): 

238 try: 

239 return self.get_display_item(int(item)) 

240 except ValueError: 

241 return item 

242 raise TypeError("Unable to interpret '{0}'.".format(item)) 

243 

244 def expected_answers(self): 

245 """ 

246 Returns the expected answers aliases. 

247 """ 

248 res = [] 

249 for i, qu in enumerate(self): 

250 exp = qu.ExpectedAnswers 

251 full = ["%s-%d-%s" % (self._col_name, i, r) for r in exp] 

252 res.append(full) 

253 return res