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