answerdb: Timestamp answers
[quizzer.git] / quizzer / answerdb.py
1 # Copyright (C) 2013 W. Trevor King <wking@tremily.us>
2 #
3 # This file is part of quizzer.
4 #
5 # quizzer is free software: you can redistribute it and/or modify it under the
6 # terms of the GNU General Public License as published by the Free Software
7 # Foundation, either version 3 of the License, or (at your option) any later
8 # version.
9 #
10 # quizzer is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License along with
15 # quizzer.  If not, see <http://www.gnu.org/licenses/>.
16
17 import codecs as _codecs
18 import datetime as _datetime
19 import json as _json
20
21 from . import __version__
22
23
24 class AnswerDatabase (dict):
25     def __init__(self, path=None, encoding=None):
26         super(AnswerDatabase, self).__init__()
27         self.path = path
28         self.encoding = encoding
29
30     def _open(self, mode='r', path=None, encoding=None):
31         if path:
32             self.path = path
33         if encoding:
34             self.encoding = encoding
35         return _codecs.open(self.path, mode, self.encoding)
36
37     def load(self, **kwargs):
38         with self._open(mode='r', **kwargs) as f:
39             data = _json.load(f)
40         version = data.get('version', None)
41         if version != __version__:
42             raise NotImplementedError('upgrade from {} to {}'.format(
43                     version, __version__))
44         self.update(data['answers'])
45
46     def save(self, **kwargs):
47         data = {
48             'version': __version__,
49             'answers': self,
50             }
51         with self._open(mode='w', **kwargs) as f:
52             _json.dump(
53                 data, f, indent=2, separators=(',', ': '), sort_keys=True)
54             f.write('\n')
55
56     def add(self, question, answer, correct):
57         if question.id not in self:
58             self[question.id] = []
59         timezone = _datetime.timezone.utc
60         timestamp = _datetime.datetime.now(tz=timezone).isoformat()
61         self[question.id].append({
62                 'answer': answer,
63                 'correct': correct,
64                 'timestamp': timestamp,
65                 })
66
67     def get_answered(self, questions):
68         return [q for q in questions if q.id in self]
69
70     def get_unanswered(self, questions):
71         return [q for q in questions if q.id not in self]
72
73     def get_correctly_answered(self, questions):
74         return [q for q in questions
75                 if True in [a['correct'] for a in self.get(q.id, [])]]
76
77     def get_never_correctly_answered(self, questions):
78         return [q for q in questions
79                 if True not in [a['correct'] for a in self.get(q.id, [])]]