/** * Luo Parse Trainer - practice Ancient Greek verb forms * Copyright (C) 2015-present Camil Staps * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ $(document).ready(function(){ var audio_positive = new Audio('public/audio/positive.wav'); var audio_negative = new Audio('public/audio/negative.wav'); var correct_answers; var input_count = 0; var checked = false; function stepFancyInput(step, val) { $('#trainer-input-fancy').html(''); var buts = {}; switch (step) { case 0: buts = { 'pr ': 'Praesens' , 'impf ': 'Imperfectum' , 'aor ': 'Aoristus' , 'fut ': 'Futurum' , 'pf ': 'Perfectum' , 'pqpf ': 'Plusquamperfectum' }; break; case 1: buts = { 'ind ': 'Indicativus' , 'conj ': 'Conjunctivus' , 'opt ': 'Optativus' , 'imp! ': 'Imperativus' , 'ptc ': 'Participium' , 'inf ': 'Infinitivus' }; break; case 2: buts = { 'act ': 'Activum' , 'med ': 'Medium' , 'pass ': 'Passivum' }; break; case 3: if (val.match(/ inf /)) { /* no buttons */ } else if (val.match(/ ptc /)) { buts = { 'M nom ev': 'M nom ev', 'F nom ev': 'F nom ev', 'N nom ev': 'N nom ev', 'M gen ev': 'M gen ev', 'F gen ev': 'F gen ev', 'N gen ev': 'N gen ev', 'M dat ev': 'M dat ev', 'F dat ev': 'F dat ev', 'N dat ev': 'N dat ev', 'M acc ev': 'M acc ev', 'F acc ev': 'F acc ev', 'N acc ev': 'N acc ev', 'M nom mv': 'M nom mv', 'F nom mv': 'F nom mv', 'N nom mv': 'N nom mv', 'M gen mv': 'M gen mv', 'F gen mv': 'F gen mv', 'N gen mv': 'N gen mv', 'M dat mv': 'M dat mv', 'F dat mv': 'F dat mv', 'N dat mv': 'N dat mv', 'M acc mv': 'M acc mv', 'F acc mv': 'F acc mv', 'N acc mv': 'N acc mv' }; } else { buts = { '1 ev': '1 ev', '2 ev': '2 ev', '3 ev': '3 ev', '1 mv': '1 mv', '2 mv': '2 mv', '3 mv': '3 mv', }; } break; } var input_field = $('#trainer-input-fancy'); var i = 0; for (k in buts) { var but = $(''); but.addClass('btn btn-default').attr('role', 'button'); if (Object.keys(buts).length > 6) but.addClass('ptc'); but.text(buts[k]).val(k); but.click(val, function(ev){ var ip = $('#trainer-input-'+input_count); ip.val(ip.val() + $(this).val()).focus(); if (step < (ev.data.match(/ inf /) ? 2 : 3)) { stepFancyInput(step + 1, ip.val()); } else { var done = checkInput(true); if ($('#trainer-input-'+input_count).parent().hasClass('has-error')) { var next = $(''); next.addClass('btn btn-warning').attr('role', 'button'); next.click(reloadVerb); if (done) { next.text('Next'); } else { next.text('Skip'); } $('#trainer-input-fancy').html(next); } } }); input_field.append(but); if (Object.keys(buts).length > 6) { if (!(++i % 3)) input_field.append($('
')); } else { input_field.append($('
')); } } } function addInput() { input_count++; var html = "
\
\
\ \ \
\
\
"; $('#trainer-input-container').append(html); $('#trainer-input-'+input_count).keyup(function(e){ if (e.keyCode == 13) { if (!checked) { checked = checkInput(false); } else { reloadVerb(); $(this) .val('') .css({backgroundColor:'transparent'}) .parent().removeClass('has-error has-success'); checked = false; } } else { $(this) .css({backgroundColor:'transparent'}) .parent().removeClass('has-error has-success'); checked = false; processInput(); } }).focus(); stepFancyInput(0, ''); } function removeInputs() { $('.trainer-input').remove(); input_count = 0; } function reloadVerb() { $('#trainer-404').hide(); $('#trainer-verb').css({color: 'gray'}); $('#trainer-answer').text(''); removeInputs(); var modes = $('input[name="mode"]:checked').map(function(){return this.value;}); var tenses = $('input[name="tense"]:checked').map(function(){return this.value;}); var voices = $('input[name="voice"]:checked').map(function(){return this.value;}); $.ajax('form/random/', { method: 'POST', data: { _token: $('#csrf').val(), mode: $.makeArray(modes).join(), tense: $.makeArray(tenses).join(), voice: $.makeArray(voices).join() }, dataType: 'json', error: function(jqxhr, status, error) { $('#trainer-404').fadeIn(); }, success: function(data, status, jqxhr) { $('#trainer-verb').text(data.form.form).css({color: 'black'}); correct_answers = []; for (var i in data.answers) { var answer = { tense: data.answers[i].tense, mode: data.answers[i].mode, voice: data.answers[i].voice, person: data.answers[i].person, gender: data.answers[i].gender, number: data.answers[i].number, case_: data.answers[i]['case'] }; correct_answers.push(answer); } addInput(); } }); } var modes = []; var tenses = []; var tenses_abbr = []; function findTense(tense) { switch (tense) { case 'pr': return 'praesens'; case 'impf': return 'imperfectum'; case 'aor': return 'aoristus'; case 'fut': return 'futurum'; case 'pf': return 'perfectum'; case 'pqpf': return 'plusquamperfectum'; default: return undefined; } } function findMode(mode) { switch (mode) { case 'ind': return 'indicativus'; case 'conj': return 'conjunctivus'; case 'opt': return 'optativus'; case 'imp!': return 'imperativus'; default: return undefined; } } function findVoice(voice) { switch (voice) { case 'act': return 'A'; case 'med': return 'M'; case 'pass': return 'P'; default: return undefined; } } function parseAnswer(parsing) { var match = parsing.match(/^\s*(pr|impf|aor|fut|pf|pqpf)\s+(ind|conj|opt|imp!)\s+(act|med|pass)\s+([123])\s*([em]v)\s*$/); if (match) { var tense = findTense(match[1]); var mode = findMode(match[2]); var voice = findVoice(match[3]); if (typeof tense=='undefined' || typeof mode=='undefined' || typeof voice=='undefined') return false; return { tense: tense, mode: mode, voice: voice, person: match[4], gender: null, number: match[5] == 'ev' ? 'sg' : 'pl', case_: null }; } match = parsing.match(/^\s*(pr|impf|aor|fut|pf|pqpf)\s+ptc\s+(act|med|pass)\s+([MFN])\s+(nom|gen|dat|acc)\s+([em]v)\s*$/); if (match) { var tense = findTense(match[1]); var voice = findVoice(match[2]); if (typeof tense=='undefined' || typeof voice=='undefined') return false; return { tense: tense, mode: 'participium', voice: voice, person: null, gender: match[3], number: match[5] == 'ev' ? 'sg' : 'pl', case_: match[4] }; } match = parsing.match(/^\s*(pr|impf|aor|fut|pf|pqpf)\s+inf\s+(act|med|pass)\s*$/); if (match) { var tense = findTense(match[1]); var voice = findVoice(match[2]); if (typeof tense=='undefined' || typeof voice=='undefined') return false; return { tense: tense, mode: 'infinitivus', voice: voice, person: null, gender: null, number: null, case_: null }; } return false; } function abbreviate(term) { switch (term) { case 'praesens': return 'pr'; case 'imperfectum': return 'impf'; case 'aoristus': return 'aor'; case 'futurum': return 'fut'; case 'perfectum': return 'pf'; case 'plusquamperfectum': return 'pqpf'; case 'indicativus': return 'ind'; case 'conjunctivus': return 'conj'; case 'optativus': return 'opt'; case 'imperativus': return 'imp!'; case 'participium': return 'ptc'; case 'infinitivus': return 'inf'; default: return term; } } function parsingToString(parsing) { var tense = parsing.tense; var mode = parsing.mode; var voice; switch (parsing.voice) { case 'A': voice = 'act'; break; case 'M': voice = 'med'; break; case 'P': voice = 'pass'; break; default: voice = parsing.voice; } var number = parsing.number == 'sg' ? 'ev' : 'mv'; var tense_mode_voice = [tense, mode, voice].join(' '); switch (parsing.mode) { case 'infinitivus': return tense_mode_voice; case 'participium': return [tense_mode_voice, parsing.gender, parsing.case_, number].join(' '); default: return [tense_mode_voice, parsing.person, number].join(' '); } } function processInput() { var input = $('#trainer-input-' + input_count); var answer = parseAnswer(input.val()); if (answer === false) { input.parent().addClass('has-error'); } else { input.parent().removeClass('has-error'); } return answer; } function checkInput(reload) { var answer = processInput(); for (var i in correct_answers) { var correct_answer = correct_answers[i]; var json = JSON.stringify(correct_answer); if (JSON.stringify(answer) == json) { $('#trainer-input-'+input_count) .css({backgroundColor: '#dff0d8'}) .parent().addClass('has-success'); if ($('#settings-audio').prop('checked')) audio_positive.play(); correct_answers.splice(i,1); if (correct_answers.length > 0) { addInput(); return false; } else { if (reload === true) { window.setTimeout(reloadVerb, 600); } return true; } } } $('#trainer-input-'+input_count) .css({backgroundColor: '#f2dede'}) .parent().addClass('has-error'); if ($('#settings-audio').prop('checked')) audio_negative.play(); $('#trainer-answer').text(' - ' + correct_answers.map(parsingToString).join(', ')); return true; } function init() { $.ajax('mode/', { dataType: 'json', success: function(data, status, jqxhr) { modes = data.map(function(d){return d.name;}); } }); $.ajax('tense/', { dataType: 'json', success: function(data, status, jqxhr) { tenses = data.map(function(d){return d.name;}); tenses_abbr = data.map(function(d){return d.abbreviation;}); } }); if (typeof reload_on_load != 'undefined' && reload_on_load) reloadVerb(); } $('#luoparsetrainer-settings .reload-verb').change(function(){ reloadVerb(); }); var help_shown = false; $('#show-hide-help').click(function(){ help_shown = !help_shown; $('#trainer-input-help').slideToggle(); $(this).text(help_shown ? 'Verberg' : 'Meer informatie'); $('#trainer-input-'+input_count).focus(); }); init(); });