Hot-keys 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
1# -*- coding: utf-8 -*-
2"""
3@file
4@brief Base classes.
5"""
8class Base:
9 """
10 Base class.
11 """
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
21 @property
22 def Id(self):
23 """
24 Returns the identifier.
25 """
26 return self._col_eid
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")))
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")}
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)
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
61 def __getitem__(self, field):
62 """
63 Returns the value associated to a field.
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)
74class Display(Base):
75 """
76 Defines how an activity should be displayed.
77 """
79 def __init__(self, eid, name):
80 """
81 @param eid unique identifier
82 @param name name
83 """
84 Base.__init__(self, eid, name)
87class LanguageBase(Base):
88 """
89 Base class for language specific content.
90 """
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
102class Notion(LanguageBase):
103 """
104 Defines what an activity intents to introduce.
105 """
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
128class Activity(LanguageBase):
129 """
130 Defines an activity, a question, a game...
131 """
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
151class ActivityGroup(Base):
152 """
153 Defines a set of activities.
154 """
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.")
170 def __len__(self):
171 """
172 Returns the number of activities.
173 """
174 return len(self._col_acts)
176 def __iter__(self):
177 """
178 To iterate on activities.
179 """
180 return self._col_acts.__iter__()
182 def __getitem__(self, item):
183 """
184 Retrieves the question.
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
198 return self._col_acts[ii]
200 def get_previous(self, current):
201 """
202 Computes the previous question or returns None
203 if does not exist.
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
214 def get_next(self, current):
215 """
216 Computes the next question or returns None
217 if does not exist.
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
228 def get_display_item(self, item):
229 """
230 Returns a displayable number.
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))
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