Allow for only one item in a bucket in questions of type "przyporzadkuj"
[edumed.git] / wtem / static / wtem / edumed.js
1 // Generated by CoffeeScript 1.6.3
2 (function() {
3   var $, Binding, EduModule, Exercise, Luki, PrawdaFalsz, Przyporzadkuj, Uporzadkuj, Wybor, Zastap, exercise,
4     __hasProp = {}.hasOwnProperty,
5     __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
6
7   $ = jQuery;
8
9   Binding = (function() {
10     function Binding(handler, element) {
11       this.handler = handler;
12       this.element = element;
13       $(this.element).data(this.handler, this);
14     }
15
16     return Binding;
17
18   })();
19
20   EduModule = (function(_super) {
21     __extends(EduModule, _super);
22
23     function EduModule(element) {
24       EduModule.__super__.constructor.call(this, 'edumodule', element);
25     }
26
27     return EduModule;
28
29   })(Binding);
30
31   Exercise = (function(_super) {
32     __extends(Exercise, _super);
33
34     function Exercise(element) {
35       var _this = this;
36       Exercise.__super__.constructor.call(this, 'exercise', element);
37       $(this.element).data("exercise-html", $(this.element).html());
38       $(".check", this.element).click(function(ev) {
39         _this.check();
40         $(".retry", _this.element).show();
41         return $(".check", _this.element).hide();
42       });
43       $(".retry", this.element).click(function(ev) {
44         return _this.retry();
45       });
46       $('.solutions', this.element).click(function() {
47         _this.show_solutions();
48         return $(".comment", _this.element).show();
49       });
50       $('.reset', this.element).click(function() {
51         return _this.reset();
52       });
53     }
54
55     Exercise.prototype.retry = function() {
56       $(".correct, .incorrect", this.element).removeClass("correct incorrect");
57       $(".check", this.element).show();
58       return $(".retry", this.element).hide();
59     };
60
61     Exercise.prototype.reset = function() {
62       $(this.element).html($(this.element).data('exercise-html'));
63       return exercise(this.element);
64     };
65
66     Exercise.prototype.piece_correct = function(qpiece) {
67       return $(qpiece).removeClass('incorrect').addClass('correct');
68     };
69
70     Exercise.prototype.piece_incorrect = function(qpiece) {
71       return $(qpiece).removeClass('correct').addClass('incorrect');
72     };
73
74     Exercise.prototype.check = function() {
75       var score, scores,
76         _this = this;
77       scores = [];
78       $(".question", this.element).each(function(i, question) {
79         return scores.push(_this.check_question(question));
80       });
81       score = [0, 0, 0];
82       $.each(scores, function(i, s) {
83         score[0] += s[0];
84         score[1] += s[1];
85         return score[2] += s[2];
86       });
87       return this.show_score(score);
88     };
89
90     Exercise.prototype.show_solutions = function() {
91       var _this = this;
92       this.reset();
93       return $(".question", this.element).each(function(i, question) {
94         return _this.solve_question(question);
95       });
96     };
97
98     Exercise.prototype.get_answers = function() {
99       var answers,
100         _this = this;
101       answers = [];
102       $('.question', this.element).each(function(i, question) {
103         return answers.push(_this.get_answer(question));
104       });
105       return answers;
106     };
107
108     Exercise.prototype.get_value_list = function(elem, data_key, numbers) {
109       var vl;
110       vl = $(elem).attr("data-" + data_key).split(/[ ,]+/).map($.trim);
111       if (numbers) {
112         vl = vl.map(function(x) {
113           return parseInt(x);
114         });
115       }
116       return vl;
117     };
118
119     Exercise.prototype.get_value_optional_list = function(elem, data_key) {
120       var mandat, opt, v, vals, _i, _len;
121       vals = this.get_value_list(elem, data_key);
122       mandat = [];
123       opt = [];
124       for (_i = 0, _len = vals.length; _i < _len; _i++) {
125         v = vals[_i];
126         if (v.slice(-1) === "?") {
127           opt.push(v.slice(0, -1));
128         } else {
129           mandat.push(v);
130         }
131       }
132       return [mandat, opt];
133     };
134
135     Exercise.prototype.show_score = function(score) {
136       var $msg;
137       $msg = $(".message", this.element);
138       $msg.text("Wynik: " + score[0] + " / " + score[2]);
139       if (score[0] >= score[2] && score[1] === 0) {
140         return $msg.addClass("maxscore");
141       } else {
142         return $msg.removeClass("maxscore");
143       }
144     };
145
146     Exercise.prototype.draggable_equal = function($draggable1, $draggable2) {
147       return false;
148     };
149
150     Exercise.prototype.draggable_accept = function($draggable, $droppable) {
151       var d, dropped, _i, _len;
152       dropped = $droppable.closest("ul, ol").find(".draggable");
153       for (_i = 0, _len = dropped.length; _i < _len; _i++) {
154         d = dropped[_i];
155         if (this.draggable_equal($draggable, $(d))) {
156           return false;
157         }
158       }
159       return true;
160     };
161
162     Exercise.prototype.draggable_move = function($draggable, $placeholder, ismultiple) {
163       var $added,
164         _this = this;
165       $added = $draggable.clone();
166       $added.data("original", $draggable.get(0));
167       if (!ismultiple) {
168         $draggable.addClass('disabled').draggable('disable');
169       }
170       $placeholder.after($added);
171       if (!$placeholder.hasClass('multiple')) {
172         $placeholder.hide();
173       }
174       if ($added.is(".add-li")) {
175         $added.wrap("<li/>");
176       }
177       $added.append('<span class="remove">x</span><div class="clr"></div>');
178       return $('.remove', $added).click(function(ev) {
179         _this.retry();
180         if (!ismultiple) {
181           $($added.data('original')).removeClass('disabled').draggable('enable');
182         }
183         if ($added.is(".add-li")) {
184           $added = $added.closest('li');
185         }
186         $added.prev(".placeholder:not(.multiple)").show();
187         return $added.remove();
188       });
189     };
190
191     Exercise.prototype.dragging = function(ismultiple, issortable) {
192       var _this = this;
193       return $(".question", this.element).each(function(i, question) {
194         var draggable_opts, self;
195         draggable_opts = {
196           revert: 'invalid',
197           helper: 'clone',
198           start: _this.retry
199         };
200         $(".draggable", question).draggable(draggable_opts);
201         self = _this;
202         return $(".placeholder", question).droppable({
203           accept: function(draggable) {
204             var $draggable, is_accepted;
205             $draggable = $(draggable);
206             is_accepted = true;
207             if (!$draggable.is(".draggable")) {
208               is_accepted = false;
209             }
210             if (is_accepted) {
211               is_accepted = self.draggable_accept($draggable, $(this));
212             }
213             if (is_accepted) {
214               $(this).addClass('accepting');
215             } else {
216               $(this).removeClass('accepting');
217             }
218             return is_accepted;
219           },
220           drop: function(ev, ui) {
221             $(ev.target).removeClass('accepting dragover');
222             return _this.draggable_move($(ui.draggable), $(ev.target), ismultiple);
223           },
224           over: function(ev, ui) {
225             return $(ev.target).addClass('dragover');
226           },
227           out: function(ev, ui) {
228             return $(ev.target).removeClass('dragover');
229           }
230         });
231       });
232     };
233
234     return Exercise;
235
236   })(Binding);
237
238   Wybor = (function(_super) {
239     __extends(Wybor, _super);
240
241     function Wybor(element) {
242       Wybor.__super__.constructor.call(this, element);
243       $(".question-piece input", element).change(this.retry);
244     }
245
246     Wybor.prototype.check_question = function(question) {
247       var all, bad, good, solution,
248         _this = this;
249       all = 0;
250       good = 0;
251       bad = 0;
252       solution = this.get_value_list(question, 'solution');
253       $(".question-piece", question).each(function(i, qpiece) {
254         var is_checked, piece_name, piece_no, should_be_checked;
255         piece_no = $(qpiece).attr('data-no');
256         piece_name = $(qpiece).attr('data-name');
257         if (piece_name) {
258           should_be_checked = solution.indexOf(piece_name) >= 0;
259         } else {
260           should_be_checked = solution.indexOf(piece_no) >= 0;
261         }
262         is_checked = $("input", qpiece).is(":checked");
263         if (should_be_checked) {
264           all += 1;
265         }
266         if (is_checked) {
267           if (should_be_checked) {
268             good += 1;
269             return _this.piece_correct(qpiece);
270           } else {
271             bad += 1;
272             return _this.piece_incorrect(qpiece);
273           }
274         } else {
275           return $(qpiece).removeClass("correct,incorrect");
276         }
277       });
278       return [good, bad, all];
279     };
280
281     Wybor.prototype.solve_question = function(question) {
282       var solution,
283         _this = this;
284       solution = this.get_value_list(question, 'solution');
285       return $(".question-piece", question).each(function(i, qpiece) {
286         var piece_name, piece_no, should_be_checked;
287         piece_no = $(qpiece).attr('data-no');
288         piece_name = $(qpiece).attr('data-name');
289         if (piece_name) {
290           should_be_checked = solution.indexOf(piece_name) >= 0;
291         } else {
292           should_be_checked = solution.indexOf(piece_no) >= 0;
293         }
294         console.log("check " + $("input[type=checkbox]", qpiece).attr("id") + " -> " + should_be_checked);
295         return $("input[type=checkbox],input[type=radio]", qpiece).prop('checked', should_be_checked);
296       });
297     };
298
299     Wybor.prototype.get_answer = function(question) {
300       var answer,
301         _this = this;
302       answer = [];
303       $('.question-piece', question).each(function(i, qpiece) {
304         var $qpiece;
305         $qpiece = $(qpiece);
306         if ($("input[type=checkbox],input[type=radio]", qpiece).is(':checked')) {
307           return answer.push($qpiece.attr('data-name'));
308         }
309       });
310       return answer;
311     };
312
313     return Wybor;
314
315   })(Exercise);
316
317   Uporzadkuj = (function(_super) {
318     __extends(Uporzadkuj, _super);
319
320     function Uporzadkuj(element) {
321       Uporzadkuj.__super__.constructor.call(this, element);
322       $('ol, ul', this.element).sortable({
323         items: "> li",
324         start: this.retry
325       });
326     }
327
328     Uporzadkuj.prototype.check_question = function(question) {
329       var all, bad, correct, pkt, pkts, positions, sorted, _i, _ref;
330       positions = this.get_value_list(question, 'original', true);
331       sorted = positions.sort();
332       pkts = $('.question-piece', question);
333       correct = 0;
334       bad = 0;
335       all = 0;
336       for (pkt = _i = 0, _ref = pkts.length; 0 <= _ref ? _i < _ref : _i > _ref; pkt = 0 <= _ref ? ++_i : --_i) {
337         all += 1;
338         if (pkts.eq(pkt).data('pos') === sorted[pkt]) {
339           correct += 1;
340           this.piece_correct(pkts.eq(pkt));
341         } else {
342           bad += 1;
343           this.piece_incorrect(pkts.eq(pkt));
344         }
345       }
346       return [correct, bad, all];
347     };
348
349     Uporzadkuj.prototype.solve_question = function(question) {
350       var p, parent, pkts, positions, sorted, _i, _len, _results;
351       positions = this.get_value_list(question, 'original', true);
352       sorted = positions.sort();
353       pkts = $('.question-piece', question);
354       pkts.sort(function(a, b) {
355         var q, w;
356         q = $(a).data('pos');
357         w = $(b).data('pos');
358         if (q < w) {
359           return 1;
360         }
361         if (q > w) {
362           return -1;
363         }
364         return 0;
365       });
366       parent = pkts.eq(0).parent();
367       _results = [];
368       for (_i = 0, _len = pkts.length; _i < _len; _i++) {
369         p = pkts[_i];
370         _results.push(parent.prepend(p));
371       }
372       return _results;
373     };
374
375     Uporzadkuj.prototype.get_answer = function(question) {
376       var answer,
377         _this = this;
378       answer = [];
379       $(".question-piece", this.element).each(function(i, qpiece) {
380         return answer.push($(qpiece).attr('data-pos'));
381       });
382       return answer;
383     };
384
385     return Uporzadkuj;
386
387   })(Exercise);
388
389   Luki = (function(_super) {
390     __extends(Luki, _super);
391
392     function Luki(element) {
393       Luki.__super__.constructor.call(this, element);
394       this.dragging(false, false);
395     }
396
397     Luki.prototype.check = function() {
398       var all, bad, correct,
399         _this = this;
400       all = $(".placeholder", this.element).length;
401       correct = 0;
402       bad = 0;
403       $(".placeholder + .question-piece", this.element).each(function(i, qpiece) {
404         var $placeholder;
405         $placeholder = $(qpiece).prev(".placeholder");
406         if ($placeholder.data('solution') === $(qpiece).data('no')) {
407           _this.piece_correct(qpiece);
408           return correct += 1;
409         } else {
410           bad += 1;
411           return _this.piece_incorrect(qpiece);
412         }
413       });
414       return this.show_score([correct, bad, all]);
415     };
416
417     Luki.prototype.solve_question = function(question) {
418       var _this = this;
419       return $(".placeholder", question).each(function(i, placeholder) {
420         var $qp;
421         $qp = $(".question-piece[data-no=" + $(placeholder).data('solution') + "]", question);
422         return _this.draggable_move($qp, $(placeholder), false);
423       });
424     };
425
426     return Luki;
427
428   })(Exercise);
429
430   Zastap = (function(_super) {
431     __extends(Zastap, _super);
432
433     function Zastap(element) {
434       var _this = this;
435       Zastap.__super__.constructor.call(this, element);
436       $(".paragraph", this.element).each(function(i, par) {
437         return _this.wrap_words($(par), $('<span class="placeholder zastap"/>'));
438       });
439       this.dragging(false, false);
440     }
441
442     Zastap.prototype.check = function() {
443       var all, bad, correct,
444         _this = this;
445       all = 0;
446       correct = 0;
447       bad = 0;
448       $(".paragraph", this.element).each(function(i, par) {
449         return $(".placeholder", par).each(function(j, qpiece) {
450           var $dragged, $qp;
451           $qp = $(qpiece);
452           $dragged = $qp.next(".draggable");
453           if ($qp.data("solution")) {
454             if ($dragged && $qp.data("solution") === $dragged.data("no")) {
455               _this.piece_correct($dragged);
456               correct += 1;
457             }
458             return all += 1;
459           }
460         });
461       });
462       return this.show_score([correct, bad, all]);
463     };
464
465     Zastap.prototype.show_solutions = function() {
466       var _this = this;
467       this.reset();
468       return $(".paragraph", this.element).each(function(i, par) {
469         return $(".placeholder[data-solution]", par).each(function(j, qpiece) {
470           var $dr, $qp;
471           $qp = $(qpiece);
472           $dr = $(".draggable[data-no=" + $qp.data('solution') + "]", _this.element);
473           return _this.draggable_move($dr, $qp, false);
474         });
475       });
476     };
477
478     Zastap.prototype.wrap_words = function(element, wrapper) {
479       var chld, i, ignore, insertWrapped, j, len, space, wordb, _i, _ref, _results;
480       ignore = /^[ \t.,:;()]+/;
481       insertWrapped = function(txt, elem) {
482         var nw;
483         nw = wrapper.clone();
484         return $(document.createTextNode(txt)).wrap(nw).parent().attr("data-original", txt).insertBefore(elem);
485       };
486       _results = [];
487       for (j = _i = _ref = element.get(0).childNodes.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; j = _ref <= 0 ? ++_i : --_i) {
488         chld = element.get(0).childNodes[j];
489         if (chld.nodeType === document.TEXT_NODE) {
490           len = chld.textContent.length;
491           wordb = 0;
492           i = 0;
493           while (i < len) {
494             space = ignore.exec(chld.textContent.substr(i));
495             if (space != null) {
496               if (wordb < i) {
497                 insertWrapped(chld.textContent.substr(wordb, i - wordb), chld);
498               }
499               $(document.createTextNode(space[0])).insertBefore(chld);
500               i += space[0].length;
501               wordb = i;
502             } else {
503               i = i + 1;
504             }
505           }
506           if (wordb < len - 1) {
507             insertWrapped(chld.textContent.substr(wordb, len - 1 - wordb), chld);
508           }
509           _results.push($(chld).remove());
510         } else {
511           _results.push(void 0);
512         }
513       }
514       return _results;
515     };
516
517     return Zastap;
518
519   })(Exercise);
520
521   Przyporzadkuj = (function(_super) {
522     __extends(Przyporzadkuj, _super);
523
524     Przyporzadkuj.prototype.is_multiple = function() {
525       var qp, _i, _len, _ref;
526       _ref = $(".question-piece", this.element);
527       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
528         qp = _ref[_i];
529         if ($(qp).attr('data-solution').split(/[ ,]+/).length > 1) {
530           return true;
531         }
532       }
533       return false;
534     };
535
536     function Przyporzadkuj(element) {
537       Przyporzadkuj.__super__.constructor.call(this, element);
538       this.multiple = this.is_multiple();
539       this.dragging(this.multiple, true);
540     }
541
542     Przyporzadkuj.prototype.draggable_equal = function(d1, d2) {
543       return d1.data("no") === d2.data("no");
544     };
545
546     Przyporzadkuj.prototype.draggable_accept = function($draggable, $droppable) {
547       var dropped;
548       dropped = $droppable.closest("ul, ol").find(".draggable");
549       return (Przyporzadkuj.__super__.draggable_accept.call(this, $draggable, $droppable)) && dropped.length === 0;
550     };
551
552     Przyporzadkuj.prototype.check_question = function(question) {
553       var all, bad_count, count, mandatory, minimum, optional, pn, pred, qp, self, v, _i, _j, _len, _len1, _ref, _ref1;
554       minimum = $(question).data("minimum");
555       count = 0;
556       bad_count = 0;
557       all = 0;
558       if (!minimum) {
559         self = this;
560         $(".subject .question-piece", question).each(function(i, el) {
561           var mandatory, v;
562           v = self.get_value_optional_list(el, 'solution');
563           mandatory = v[0];
564           return all += mandatory.length;
565         });
566       }
567       _ref = $(".predicate [data-predicate]", question);
568       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
569         pred = _ref[_i];
570         pn = $(pred).attr('data-predicate');
571         _ref1 = $(".question-piece", pred);
572         for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
573           qp = _ref1[_j];
574           v = this.get_value_optional_list(qp, 'solution');
575           mandatory = v[0];
576           optional = v[1];
577           if (mandatory.indexOf(pn) >= 0 || (minimum && optional.indexOf(pn) >= 0)) {
578             count += 1;
579             this.piece_correct(qp);
580           } else {
581             bad_count += 1;
582             this.piece_incorrect(qp);
583           }
584         }
585       }
586       return [count, bad_count, all];
587     };
588
589     Przyporzadkuj.prototype.solve_question = function(question) {
590       var $ph, $pr, draggables, m, mandatory, minimum, optional, qp, v, _i, _len, _ref, _results;
591       minimum = $(question).data("min");
592       _ref = $(".subject .question-piece", question);
593       _results = [];
594       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
595         qp = _ref[_i];
596         v = this.get_value_optional_list(qp, 'solution');
597         mandatory = v[0];
598         optional = v[1];
599         if (minimum) {
600           draggables = mandatory.count(optional).slice(0, minimum);
601         } else {
602           draggables = mandatory;
603         }
604         _results.push((function() {
605           var _j, _len1, _results1;
606           _results1 = [];
607           for (_j = 0, _len1 = draggables.length; _j < _len1; _j++) {
608             m = draggables[_j];
609             $pr = $(".predicate [data-predicate=" + m + "]", question);
610             $ph = $pr.find(".placeholder:visible");
611             _results1.push(this.draggable_move($(qp), $ph.eq(0), this.multiple));
612           }
613           return _results1;
614         }).call(this));
615       }
616       return _results;
617     };
618
619     Przyporzadkuj.prototype.get_answer = function(question) {
620       var answer,
621         _this = this;
622       answer = {};
623       $(".predicate [data-predicate]", question).each(function(i, subjects) {
624         var predicate;
625         predicate = $(subjects).attr('data-predicate');
626         answer[predicate] = [];
627         return $('.question-piece', subjects).each(function(i, qpiece) {
628           var $qpiece;
629           $qpiece = $(qpiece);
630           return answer[predicate].push($qpiece.attr('data-id'));
631         });
632       });
633       return answer;
634     };
635
636     return Przyporzadkuj;
637
638   })(Exercise);
639
640   PrawdaFalsz = (function(_super) {
641     __extends(PrawdaFalsz, _super);
642
643     function PrawdaFalsz(element) {
644       var qp, _i, _len, _ref,
645         _this = this;
646       PrawdaFalsz.__super__.constructor.call(this, element);
647       _ref = $(".question-piece", this.element);
648       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
649         qp = _ref[_i];
650         $(".true", qp).click(function(ev) {
651           ev.preventDefault();
652           _this.retry();
653           $(ev.target).closest(".question-piece").data("value", "true");
654           return $(ev.target).addClass('chosen').siblings('a').removeClass('chosen');
655         });
656         $(".false", qp).click(function(ev) {
657           ev.preventDefault();
658           _this.retry();
659           $(ev.target).closest(".question-piece").data("value", "false");
660           return $(ev.target).addClass('chosen').siblings('a').removeClass('chosen');
661         });
662       }
663     }
664
665     PrawdaFalsz.prototype.check_question = function() {
666       var all, bad, good, qp, _i, _len, _ref;
667       all = 0;
668       good = 0;
669       bad = 0;
670       _ref = $(".question-piece", this.element);
671       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
672         qp = _ref[_i];
673         if ($(qp).data("solution").toString() === $(qp).data("value")) {
674           good += 1;
675           this.piece_correct(qp);
676         } else {
677           bad += 1;
678           this.piece_incorrect(qp);
679         }
680         all += 1;
681       }
682       return [good, bad, all];
683     };
684
685     PrawdaFalsz.prototype.show_solutions = function() {
686       var qp, _i, _len, _ref, _results;
687       this.reset();
688       _ref = $(".question-piece", this.element);
689       _results = [];
690       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
691         qp = _ref[_i];
692         if ($(qp).data('solution') === true) {
693           _results.push($(".true", qp).click());
694         } else {
695           _results.push($(".false", qp).click());
696         }
697       }
698       return _results;
699     };
700
701     PrawdaFalsz.prototype.get_answer = function(question) {
702       var answer,
703         _this = this;
704       answer = [];
705       $(".question-piece", this.element).each(function(i, qpiece) {
706         return answer.push($(qpiece).data('value') || '-');
707       });
708       return answer;
709     };
710
711     return PrawdaFalsz;
712
713   })(Exercise);
714
715   exercise = function(ele) {
716     var cls, es;
717     es = {
718       wybor: Wybor,
719       uporzadkuj: Uporzadkuj,
720       luki: Luki,
721       zastap: Zastap,
722       przyporzadkuj: Przyporzadkuj,
723       prawdafalsz: PrawdaFalsz
724     };
725     cls = es[$(ele).attr('data-type')];
726     return new cls(ele);
727   };
728
729   window.edumed = {
730     'EduModule': EduModule
731   };
732
733   $(document).ready(function() {
734     new EduModule($("#book-text"));
735     return $(".exercise").each(function(i, el) {
736       return exercise(this);
737     });
738   });
739
740 }).call(this);