prawda/falsz questions
[librarian.git] / librarian / pyhtml.py
1 # -*- coding: utf-8 -*-
2 #
3 # This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
4 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
5 #
6 from lxml import etree
7 from librarian import OutputFile, RDFNS, DCNS
8 from xmlutils import Xmill, tag, tagged, ifoption
9  
10
11 class EduModule(Xmill):
12     def __init__(self, *args):
13         super(EduModule, self).__init__(*args)
14         self.activity_counter = 0
15
16     def handle_powiesc(self, element):
17         return u"""
18 <div class="module" id="book-text">
19  <span class="teacher-toggle">
20   <input type="checkbox" name="teacher-toggle" id="teacher-toggle"/>
21   <label for="teacher-toggle">Pokaż treść dla nauczyciela</label>
22  </span>
23
24 """, u"</div>"
25
26
27     handle_autor_utworu = tag("span", "author")
28     handle_nazwa_utworu = tag("h1", "title")
29     handle_dzielo_nadrzedne = tag("span", "collection")
30     handle_podtytul = tag("span", "subtitle")
31     handle_naglowek_akt = handle_naglowek_czesc = handle_srodtytul = tag("h2")
32     handle_naglowek_scena = handle_naglowek_rozdzial = tag('h3')
33     handle_naglowek_osoba = handle_naglowek_podrozdzial = tag('h4')
34     handle_akap = handle_akap_dialog = handle_akap_cd = tag('p', 'paragraph')
35     handle_strofa = tag('div', 'stanza')
36
37     def handle_aktywnosc(self, element):
38         self.activity_counter += 1
39         self.options = {
40             'activity': True, 
41             'activity_counter': self.activity_counter
42             }
43         submill = EduModule()
44
45         opis = submill.generate(element.xpath('opis')[0])
46
47         n = element.xpath('wskazowki')
48         if n: wskazowki = submill.generate(n[0])
49
50         else: wskazowki = ''
51         n = element.xpath('pomoce')
52
53         if n: pomoce = submill.generate(n[0])
54         else: pomoce = ''
55
56         forma = ''.join(element.xpath('forma/text()'))
57
58         czas = ''.join(element.xpath('czas/text()'))
59
60         counter = self.activity_counter
61
62         return u"""
63 <div class="activity">
64  <div class="text">%(counter)d. 
65   %(opis)s
66   %(wskazowki)s
67  </div>
68  <div class="info">
69   <p>Czas: %(czas)s min</p>
70   <p>Forma: %(forma)s</p>
71   %(pomoce)s
72  </div>
73  <div class="clearboth"></div>
74 </div>
75 """ % locals()
76
77     handle_opis = ifoption(activity=False)(tag('div', 'description'))
78     handle_wskazowki = ifoption(activity=False)(tag('div', ('hints', 'teacher')))
79     
80     @ifoption(activity=False)
81     @tagged('div', 'materials')
82     def handle_pomoce(self, _):
83         return "Pomoce: ", ""
84     
85     def handle_czas(self, *_):
86         return
87
88     def handle_forma(self, *_):
89         return
90             
91     def handle_cwiczenie(self, element):
92         excercise_handlers = {
93             'wybor': Wybor,
94             'uporzadkuj': Uporzadkuj,
95             'luki': Luki,
96             'zastap': Zastap,
97             'przyporzadkuj': Przyporzadkuj,
98             'prawdafalsz': PrawdaFalsz
99             }
100         
101         typ = element.attrib['typ']
102         handler = excercise_handlers[typ](self.options)
103         return handler.generate(element)
104
105     # Lists
106     def handle_lista(self, element, attrs={}):
107         ltype = element.attrib.get('typ', 'punkt')
108         if ltype == 'slowniczek':
109             self.options = {'slowniczek': True}
110             return '<div class="slowniczek">', '</div>'
111 ### robie teraz punkty wyboru
112         listtag = {'num': 'ol', 
113                'punkt': 'ul', 
114                'alfa': 'ul', 
115                'czytelnia': 'ul'}[ltype]
116
117         classes = attrs.get('class', '')
118         if classes: del attrs['class']
119             
120         attrs_s = ' '.join(['%s="%s"' % kv for kv in attrs.items()])
121         if attrs_s: attrs_s = ' ' + attrs_s
122             
123         return '<%s class="lista %s %s"%s>' % (listtag, ltype, classes, attrs_s), '</%s>' % listtag
124
125     def handle_punkt(self, element):
126         if self.options['slowniczek']:
127             return '<dl>', '</dl>'
128         else:
129             return '<li>', '</li>'
130
131     def handle_rdf__RDF(self, _):
132         # ustal w opcjach  rzeczy :D
133         return 
134
135
136 class Excercise(EduModule):
137     def __init__(self, *args, **kw):
138         self.question_counter = 0
139         super(Excercise, self).__init__(*args, **kw)
140
141     def handle_rozw_kom(self, element):
142         return None
143
144     def handle_cwiczenie(self, element):
145         self.options = {'excercise': element.attrib['typ']}
146         self.question_counter = 0
147         self.piece_counter = 0
148
149         pre = u"""
150 <div class="excercise %(typ)s" data-type="%(typ)s">
151 <form action="#" method="POST">
152 """ % element.attrib
153         post = u"""
154 <div class="buttons">
155 <span class="message"></span>
156 <input type="button" class="check" value="sprawdź"/>
157 <input type="button" class="solutions" value="pokaż rozwiązanie"/>
158 </div>
159 </form>
160 </div>
161 """
162         # Add a single <pytanie> tag if it's not there
163         if not element.xpath(".//pytanie"):
164             qpre, qpost = self.handle_pytanie(element)
165             pre = pre + qpre
166             post = qpost + post
167         return pre, post
168  
169     def handle_pytanie(self, element):
170         """This will handle <cwiczenie> element, when there is no <pytanie>
171         """
172         self.question_counter += 1
173         self.piece_counter = 0
174         solution = element.attrib.get('rozw', None)
175         if solution: solution_s = ' data-solution="%s"' % solution
176         else: solution_s = ''
177
178         return '<div class="question" data-no="%d" %s>' %\
179             (self.question_counter, solution_s), \
180     "</div>"
181
182
183 class Wybor(Excercise):
184     def handle_punkt(self, element):
185         if self.options['excercise'] and element.attrib.get('nazwa', None):
186             qc = self.question_counter
187             self.piece_counter += 1
188             no = self.piece_counter
189             eid = "q%(qc)d_%(no)d" % locals()
190             aname = element.attrib.get('nazwa', None)
191             return u"""
192 <li class="question-piece" data-qc="%(qc)d" data-no="%(no)d" data-name="%(aname)s">
193 <input type="checkbox" name="" id="%(eid)s" />
194 <label for="%(eid)s">
195 """ % locals(), u"</label></li>"
196
197         else:
198             return super(Wybor, self).handle_punkt(element)
199
200
201 class Uporzadkuj(Excercise):
202     def handle_pytanie(self, element):
203         """
204 Overrides the returned content default handle_pytanie
205         """
206         # we ignore the result, returning our own
207         super(Uporzadkuj, self).handle_pytanie(element)
208         order_items = element.xpath(".//punkt/@rozw")
209
210         return u"""<div class="question" data-original="%s" data-no="%s">""" % \
211             (','.join(order_items), self.question_counter), \
212             u"""</div>"""
213
214     def handle_punkt(self, element):
215         return """<li class="question-piece" data-pos="%(rozw)s"/>""" \
216             % element.attrib,\
217             "</li>"
218
219
220 class Luki(Excercise):
221     def handle_luka(self, element):
222         return '<input type="text" class="luka question-piece" data-solution="%s"></input>' % element.text
223
224
225 class Zastap(Excercise):
226     def handle_zastap(self, element):
227         return '<span class="zastap question-piece" data-solution="%(rozw)s">' % element.attrib, '</span>'
228
229
230 class Przyporzadkuj(Excercise):
231     def handle_lista(self, lista):
232         print "in lista %s %s" % (lista.attrib, self.options)
233         if 'nazwa' in lista.attrib:
234             attrs = {
235                 'data-name': lista.attrib['nazwa'],
236                 'class': 'predicate'
237                 }
238             self.options = {'predicate': True}
239         elif 'cel' in lista.attrib:
240             attrs = {
241                 'data-target': lista.attrib['cel'],
242                 'class': 'subject'
243                 }
244             self.options = {'subject': True}
245         else:
246             attrs = {}
247         pre, post = super(Przyporzadkuj, self).handle_lista(lista, attrs)
248         return pre, post + '<br class="clr"/>'
249
250     def handle_punkt(self, element):
251         print "in punkt %s %s" % (element.attrib, self.options)
252
253         if self.options['subject']:
254             return '<li data-solution="%(rozw)s" class="question-piece draggable">' % element.attrib, '</li>'
255         elif self.options['predicate']:
256             print etree.tostring(element, encoding=unicode)
257             return '<li data-predicate="%(nazwa)s">' % element.attrib, '<ul class="subjects droppable"></ul></li>'
258         else:
259             return super(Przyporzadkuj, self).handle_punkt(element)
260
261
262 class PrawdaFalsz(Excercise):
263     def handle_punkt(self, element):
264         if 'rozw' in element.attrib:
265             return u'''<li data-solution="%s" class="question-piece">
266             <span class="buttons">
267             <a href="#" data-value="true" class="true">Prawda</a>
268             <a href="#" data-value="false" class="false">Fałsz</a>
269         </span>''' % {'prawda': 'true', 'falsz': 'false'}[element.attrib['rozw']], '</li>'
270         else:
271             return super(PrawdaFalsz, self).handle_punkt(element)
272
273
274 def transform(wldoc, stylesheet='edumed', options=None, flags=None):
275     """Transforms the WL document to XHTML.
276
277     If output_filename is None, returns an XML,
278     otherwise returns True if file has been written,False if it hasn't.
279     File won't be written if it has no content.
280     """
281     edumod = EduModule(options)
282 #    from pdb import set_trace; set_trace()
283     html = edumod.generate(wldoc.edoc.getroot())
284
285     return OutputFile.from_string(html.encode('utf-8'))