package ONO::FW::Edu::Apps::Modules::Verbs;
################################################################################
# COPYRIGHT / LICENSE #
################################################################################
#
# This file is part of the ONO Software Project.
#
# Copyright (C) 2022-2026 Jos Kirps and The Joopita Project [ASBL]
# Copyright (C) 2011-2022 Jos Kirps and Joopita Research ASBL
# Copyright (C) 2006-2011 Jos Kirps and The Joopita Project
# Copyright (C) 2001-2006 Jos Kirps and The WobbleWolf Project
#
# This file, as well as many other parts of the ONO Software Project or
# related elements, are FREE SOFTWARE available under the ARTISTIC LICENSE 2.0.
#
# 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.
#
# For the full license, see /ono/osr/license/LICENSE.txt, or write to
# jos_AT_kirps_DOT_com or contact_AT_joopita_DOT_com.
#
################################################################################
# END OF COPYRIGHT / LICENSE, HERE COMES THE CODE ... #
################################################################################
#: This module is a front end application module wrapper that has been
#: created for the Morzino Project (morzino.com) and that has been released
#: as Open Source software.
#:
#: Note that this is NOT a self-contained application, it is only a wrapper
#: that makes heavy use of the ONO Perl Framework application engine.
use strict;
use ONO::Lib::Basic;
use ONO::FW::Edu::Apps::ToolBox;
use ONO::FW::Edu::Apps::Modules::WorksheetMaker::Input;
use ONO::FW::Apps::ToolBox;
use ONO::Lib::PDF::Draw;
use ONO::Lib::PDF::ToolBox;
use ONO::Lib::Data::Numbers::Roman;
use ONO::FW::Apps::Core;
use ONO::FW::Apps::Core::Graphics;
use ONO::Lib::Parser;
use ONO::IO;
use ONO::FW::Apps::PDF;
sub learn {
my (
$self,
$option,
$vars_ref,
$HTTP,
$BASE,
) = @_;
################################################################
# INIT - BEGIN
################################################################
my (
$db,
$community,
$action_url,
$form,
$format,
$canvas,
$pdfkey,
$sec,$min,$hour,
$mday,$mon,$year,
$wday,$yday,$timestamp,
$lang,
$BLK_ref,
$vars_ref,
) = ONO::FW::Apps::Core->init($vars_ref);
my %vars = %$vars_ref;
my %BLK = %$BLK_ref;
my $app = "verbs_$option";
if ($option =~ /^(en|de|fr)/) {
$option = $1;
}
if ($option =~ /^ge/) {
$option = "de";
}
if ($vars{'output_worksheet_maker'}) {
my (@options,$options_num);
foreach my $opt ('en','de','fr') {
if ($vars{"app_input_lang_use_$opt"}) {
@options = (@options,$opt);
$options_num++;
}
}
if ($options_num) {
$option = $options[int(rand($options_num))];
} else {
$option = "en";
}
}
if (ONO::IO->devstation) {
# $option = "en";
}
ONO::FW::Apps::Core->now("",$app,$vars{'app_lang'});
my $WEB;
$vars{'app_input_print_options_title_default'} = $BLK{'Verbs'};
$vars{"app_conf_input_tense_1"} = "present";
$vars{"app_conf_input_tense_2"} = "past";
$vars{"app_conf_input_tense_3"} = "future";
my $err_prono = "forgot the pronoun (###)?";
if ($vars{'app_lang'} eq "de") {
$vars{"app_conf_input_tense_1"} = "Gegenwart";
$vars{"app_conf_input_tense_2"} = "Vergangenheit";
$vars{"app_conf_input_tense_3"} = "Zukunft";
$err_prono = "Pronomen (###) vergessen?";
}
if ($vars{'app_lang'} eq "fr") {
$vars{"app_conf_input_tense_1"} = "présent";
$vars{"app_conf_input_tense_2"} = "passé";
$vars{"app_conf_input_tense_3"} = "futur";
$err_prono = "oublié le pronom (###) ?";
}
if ($vars{'app_lang'} eq "lu") {
$vars{"app_conf_input_tense_1"} = "Géigewaart";
$vars{"app_conf_input_tense_2"} = "Vergaangenheet";
$vars{"app_conf_input_tense_3"} = "Zukunft";
$err_prono = "Pronom (###) vergiess?";
}
my ($SING,$PLUR) = ('sing','plur');
if ($option eq "de") {
($SING,$PLUR) = ('Sing','Plur');
}
my ($codes_ref,$tenses_ref,$pres_ref,$past_ref,$fut_ref) = ONO::FW::Apps::Core->lang_tenses($option);
my @codes = @$codes_ref;
my @tenses = @$tenses_ref;
foreach my $key (keys %vars) {
if ($key =~ /^output_add_group_/) {
$vars{'output_add'}++;
}
if ($option eq "en") {
if ($key =~ /^output_web_answer/ && $vars{$key} !~ /^I/) {
$vars{$key} = lc $vars{$key};
}
} else {
if ($key =~ /^output_web_answer/) {
$vars{$key} = ONO::Lib::Basic->umlaut_make_lowercase($vars{$key});
}
}
if ($option eq "de") {
if ($key =~ /^output_web_answer/) {
$vars{$key} =~ s/gewunken/gewinkt/i;
}
}
}
$WEB .= ONO::FW::Apps::Core->output_paper_save($pdfkey,$BLK_ref,\%vars,$HTTP,$BASE,"$year$mon$mday");
# if (ONO::IO->devstation) {
# $vars{'username'}="";
# }
if ((ONO::FW::Apps::Core->running(\%vars,$db) && !$vars{'output_add_verb'}) || $vars{'output_print_verbs'}) {
#############################################################
# WORKSHEET MAKER
#############################################################
if ($vars{'output_worksheet_maker'}) {
$vars_ref = ONO::FW::Edu::Apps::Modules::WorksheetMaker::Input->vars(\%vars);
%vars = %$vars_ref;
}
#############################################################
# ONLINE TRAINING
#############################################################
$WEB .= ONO::FW::Apps::Core->blockbackbutton($BASE,$vars_ref);
if ($vars{'output_web'} || $vars{'output_paper'} || $vars{'output_print_verbs'}) {
my $question_number = ONO::FW::Apps::Core->question_number($vars{'output_web_question_number'});
my (
$focus_on,
$page,$pages,%cache,
$whilecounter,$stats_switches,
$PDF_OPTS,
$stat_correct,$stat_wrong,$stat_todo,$stat_todo_total,
);
my $questions_per_page = 1;
if ($vars{'output_paper'}) {
$PDF_OPTS = ONO::FW::Apps::Core->headers_options($BLK_ref,$vars_ref);
ONO::FW::Apps::PDF->new("$BASE/pdf/pdf-$pdfkey.pdf","",$format);
$vars{'app_input_multiple_questions_per_page'}++;
$questions_per_page = 20;
}
# build the list of verbs, persons, and tenses...
my ($VERBLIST,@lessons,$lessons_loaded,@list,$list_loaded,%used,%VERBCACHE);
my $VERBDIR = "ono-data/school/verbs_$option";
# verbs
if ($vars{'app_input_verblist'} =~ /:/) {
$VERBLIST = $vars{'app_input_verblist'};
} else {
foreach my $key (keys %vars) {
if ($vars{$key}) {
if ($key =~ /^app_input_use_verb_(.*?)$/) {
my $handle = $1;
if (ONO::IO->devstation) {
$WEB .= qq~VERB: $handle ($key / $handle), ~;
}
if ($handle =~ /^(custom|group)_(.*?)$/) {
my $type = $1;
my $group = $2;
# custom
if (ONO::IO->devstation) {
$WEB .= qq~CUSTOM GROUP: $option / $type / $group<br>~;
}
if ($type eq "custom") {
# use ALL verbs
if ($group eq "ALL") {
my $ALLFILE = "ono-data/school/verbs_$option/structure/list.txt";
my @ALLFILES;
foreach my $line (ONO::IO->list($ALLFILE)) {
if ($line =~ /[a-z]/) {
$line =~ s~(\n|\r|\t)~~g;
if ($line =~ m~^(.*?)-(.*?)$~) {
$line = $1;
}
my $vname = $line;
my $vfile = ONO::Lib::Basic->umlaut_simplify($vname);
$vfile =~ s~ ~_~g;
if (ONO::IO->exists("ono-data/school/verbs_$option/verbs/verb_$vfile.txt")) {
@ALLFILES = (@ALLFILES,qq~$vfile:$vname;~);
}
}
}
my $num = @ALLFILES;
for (my $i = 0; $i < 32; $i++) {
$VERBLIST .= $ALLFILES[int(rand($num))];
}
if (ONO::IO->devstation) {
$WEB .= qq~LOADING FROM: $ALLFILE, VERBLIST = $VERBLIST<br>~;
}
}
# custom lists -
if (length $group == 10) {
my $APPCONF = "var/community/$community/apps/lists/".ONO::IO->deepdir($group)."/$group.appconf";
foreach my $line (ONO::IO->list($APPCONF)) {
if ($line =~ /^"(.*?)"/) {
my $vname = $1;
my $vfile = ONO::Lib::Basic->umlaut_simplify($vname);
$vfile =~ s~ ~_~g;
if (ONO::IO->exists("ono-data/school/verbs_$option/verbs/verb_$vfile.txt")) {
$VERBLIST .= qq~$vfile:$vname;~;
}
}
}
if (ONO::IO->devstation) {
$WEB .= qq~LOADING FROM: $APPCONF, VERBLIST = $VERBLIST<br>~;
}
}
# top lists
if ($group =~ /^top_(.*?)$/) {
my $top = $1;
my $top_counter;
if (ONO::IO->devstation) {
$WEB .= qq~LOADING TOP $top FROM verbs_$option/structure/top100.txt, ~;
}
foreach my $line (ONO::IO->list("ono-data/school/verbs_$option/structure/top100.txt")) {
if ($line =~ /[a-z]/) {
$line =~ s~(\n|\r|\t)~~g;
my $vname = $line;
my $vfile = ONO::Lib::Basic->umlaut_simplify($line);
$vfile =~ s~ ~_~g;
if (ONO::IO->exists("ono-data/school/verbs_$option/verbs/verb_$vfile.txt") && $top_counter < $top) {
$VERBLIST .= qq~$vfile:$vname;~;
$top_counter++;
}
}
}
}
# french - this will remain for now, for compatibility reasons
# may be removed in 2026...
if ($option eq "fr") {
if ($group =~ /^(c31|c32|c41|c42)$/) {
my $file = "ep3";
if ($group eq "c32") {
$file = "ep4";
}
if ($group eq "c41") {
$file = "ep5";
}
if ($group eq "c42") {
$file = "ep6";
}
foreach my $line (ONO::IO->list("$VERBDIR/structure/$file.txt")) {
$line =~ s~(\n|\r|\t)~~g;
my @lp = split(/-/,$line);
if ($lp[0] && $lp[1] && ONO::IO->exists("ono-data/school/verbs_$option/verbs/verb_$lp[1].txt")) {
$VERBLIST .= qq~$lp[1]:$lp[0];~;
}
}
} else {
if (!$lessons_loaded) {
$lessons_loaded++;
@lessons = ONO::IO->list("$VERBDIR/structure/lessons.txt");
}
my @cache_verbs;
foreach my $lesson (@lessons) {
$lesson =~ s~(\n|\r|\t)~~g;
my @lp = split(/\^/,$lesson);
if (
(
(substr($group,1,2) == 31 && $lp[0] =~ /^3/) ||
(substr($group,1,2) == 32 && $lp[0] =~ /^4/) ||
(substr($group,1,2) == 41 && $lp[0] =~ /^5/) ||
(substr($group,1,2) == 42 && $lp[0] =~ /^6/)
) && (substr($group,4,2) == substr($lp[0],1,2))
) {
foreach my $verb (split(/:/,$lp[1])) {
if (!$used{$verb}) {
$used{$verb}++;
if (!$list_loaded) {
$list_loaded++;
@list = ONO::IO->list("$VERBDIR/structure/list.txt");
}
my $verbname;
foreach my $line (@list) {
$line =~ s~(\n|\r|\t)~~g;
my @lp = split(/-/,$line);
if ($lp[1] eq $verb) {
$verbname = $lp[0];
}
}
if ($verbname && ONO::IO->exists("ono-data/school/verbs_$option/verbs/verb_$verb.txt")) {
$VERBLIST .= qq~$verb:$verbname;~;
}
}
}
}
}
}
}
}
# group
if ($type eq "group") {
# french
if ($option eq "fr") {
foreach my $line (ONO::IO->list("$VERBDIR/structure/list_$group.txt")) {
if ($line =~ /-/) {
$line =~ s~(\n|\r|\t)~~g;
my @lp = split(/-/,$line);
if (!$used{$lp[1]} && ONO::IO->exists("ono-data/school/verbs_$option/verbs/verb_$lp[1].txt")) {
$used{$lp[1]}++;
$VERBLIST .= qq~$lp[1]:$lp[0];~;
}
}
}
}
}
} else {
# app_info_use_verb_... may be missing in exercise mode, so load it...
if ($vars{'exercise'} && !$vars{"app_info_use_verb_$handle"}) {
if ($option eq "en") {
$vars{"app_info_use_verb_$handle"} = $handle;
} else {
if ($option eq "fr" && ($handle =~ /^(s|se)_/)) {
foreach my $test (ONO::IO->list("$VERBDIR/structure/list_prono.txt")) {
$test =~ s~(\n|\r|\t)~~g;
my @tp = split(/-/,$test);
if ($tp[1] eq $handle) {
$vars{"app_info_use_verb_$handle"} = $tp[0];
}
}
} else {
foreach my $test (ONO::IO->list("$VERBDIR/structure/list.txt")) {
$test =~ s~(\n|\r|\t)~~g;
my @tp = split(/-/,$test);
if ($tp[1] eq $handle) {
$vars{"app_info_use_verb_$handle"} = $tp[0];
}
}
}
}
}
# use the verb if app_info_use_verb_... exists
if ($vars{"app_info_use_verb_$handle"}) {
if (!$used{$handle} && ONO::IO->exists("ono-data/school/verbs_$option/verbs/verb_$handle.txt")) {
$used{$handle}++;
$VERBLIST .= qq~$handle:$vars{"app_info_use_verb_$handle"};~;
}
}
}
}
}
}
$vars{'app_input_verblist'} = $VERBLIST;
}
my @use_verbs = split(/;/,$VERBLIST);
my $use_verb_num = @use_verbs;
if ($use_verb_num < 1) {
@use_verbs = split(/;/,ONO::FW::Apps::Core->lang_verbs_default($option));
$use_verb_num = @use_verbs;
}
# persons
my @use_persons;
for (my $p = 1; $p < 7; $p++) {
if ($vars{"app_input_person_$p"}) {
@use_persons = (@use_persons,$p);
}
}
my $use_pers_num = @use_persons;
if ($use_pers_num < 1) {
@use_persons = (1);
$use_pers_num = 1;
}
# tenses
my (@use_tenses,%use_tenses_names);
foreach my $tense (@tenses) {
my @tp = split(/:/,$tense);
if ($vars{"app_input_tense_use_$tp[0]"}) {
@use_tenses = (@use_tenses,$tp[0]);
$use_tenses_names{$tp[0]} = $tp[1];
}
}
my $use_tenses_num = @use_tenses;
if ($use_tenses_num < 1) {
my @tp = split(/:/,$tenses[0]);
@use_tenses = ($tp[0]);
$use_tenses_names{$tp[0]} = $tp[1];
}
my @persons = ONO::FW::Apps::Core->lang_verbs_persons($option);
# end of generator
if ($vars{'output_web_continue'}) {
for (my $h = 0; $h < 21; $h++) {
$vars{"output_web_hints_$h"} = 0;
}
}
# start verb cache
if ($vars{'output_paper'} || $vars{'output_print_verbs'} || $vars{'output_web_continue'} || ($vars{'output_web'} && !$vars{"output_web_cache_que1_0"} && $vars{'app_input_multiple_questions_per_page'})) {
if (ONO::IO->devstation) {
$WEB .= qq~CACHE IS BEING LOADED<br>~;
}
foreach my $verb (@use_verbs) {
my @vp = split(/:/,$verb);
if (ONO::IO->exists("$VERBDIR/verbs/verb_$vp[0].txt")) {
foreach my $line (ONO::IO->list_raw("$VERBDIR/verbs/verb_$vp[0].txt")) {
$line =~ s~(\n|\r|\t)~~g;
my @lp = split(/\^/,$line);
if ($lp[0] && $lp[1]) {
$lp[1] =~ s~(\<|\>)~~g;
$VERBCACHE{"$vp[0]_$lp[0]"} = $lp[1];
}
}
if ($option eq "de") {
%VERBCACHE = (%VERBCACHE,&german_verb_builder("",$vp[0],$VERBCACHE{"$vp[0]_HILF_VERB"},$vp[1],$VERBCACHE{"$vp[0]_PART_PERF"}));
}
}
}
}
# end of verb cache
# start print mode
if ($vars{'output_print_verbs'}) {
ONO::FW::Apps::PDF->new("$BASE/pdf/pdf-$pdfkey.pdf","",$format);
my $verb_counter;
foreach my $verb (sort @use_verbs) {
$verb_counter++;
if ($verb_counter > 1) {
ONO::FW::Apps::PDF->page("",$format);
}
my @vp = split(/:/,$verb);
if ($option eq "en") {
$vp[1] = "to $vp[1]";
}
ONO::FW::Apps::Core->headers(\%vars,$format);
ONO::FW::Apps::PDF->title($vp[1],$PDF_OPTS,$vars{'app_input_print_options_code'},$format);
my ($h,$v) = (9,9);
my %TENSES;
foreach my $tense (@tenses) {
my @tp = split(/:/,$tense);
$TENSES{$tp[0]} = $tp[1];
}
my @tenses;
if ($option eq "en") {
($h,$v) = (4,3);
@tenses = (
'PRS', 'IMP', 'FUT',
'CON', 'PCO', 'FUP',
'PRC', 'PRP', '',
'PAC', 'PAP', '',
);
}
if ($option eq "de") {
($h,$v) = (3,2);
@tenses = (
'PRS', 'IMP',
'FUT', 'PER',
'IMPE', 'PQP',
);
}
if ($option eq "fr") {
($h,$v) = (4,3);
@tenses = (
'IP', 'IMP', 'FUT',
'IMPE', 'PC', 'FP',
'PART_PRES', 'PR', 'CON',
'PART_PASSE', 'PS', 'SUBJ',
);
}
for (my $l = 0; $l < $h+1; $l++) {
ONO::Lib::PDF::Draw->line($canvas,0,$l*(190/$h),170,$l*(190/$h),0.25);
}
for (my $l = 0; $l < $v+1; $l++) {
ONO::Lib::PDF::Draw->line($canvas,$l*(170/$v),0,$l*(170/$v),190,0.25);
}
my ($pdf_x,$pdf_y,$tense_counter);
foreach my $tense (@tenses) {
$tense_counter++;
if ($vars{"app_input_tense_use_$tense"}) {
ONO::Lib::PDF::Draw->font('HB');
ONO::Lib::PDF::Draw->text($canvas,$pdf_x+4,$pdf_y+8,$TENSES{$tense});
ONO::Lib::PDF::Draw->font('H');
if ($VERBCACHE{"$vp[0]_$tense"}) {
ONO::Lib::PDF::Draw->text($canvas,$pdf_x+4,$pdf_y+16,$VERBCACHE{"$vp[0]_$tense"});
}
my $offset = 14;
my $next_y = 5;
if ($option eq "fr") {
$offset = 16;
}
if ($option eq "de") {
$offset = 11;
$next_y = 7.5;
}
for (my $p = 1; $p < 7; $p++) {
if ($VERBCACHE{"$vp[0]_$tense$p"}) {
my $special;
if (
($option eq "fr" && $tense =~ /^(IP|IMP|PC|PR|PS|FUT|FP|CON)$/) ||
($option eq "en" && $tense =~ /^(PRS|IMP|FUT|FUP|PRC|PAC|PAP)$/) ||
($option eq "de" && $tense =~ /^(PRS|IMP)$/)
) {
$special++;
my @pp = split(/ /,$VERBCACHE{"$vp[0]_$tense$p"});
$pp[0] =~ s~:(.*)$~~;
my @add = ($pp[2],$pp[3],$pp[4]);
if ($VERBCACHE{"$vp[0]_$tense$p"} =~ /j'/) {
@pp = split(/'/,$VERBCACHE{"$vp[0]_$tense$p"});
$pp[0] .= "'";
}
if ($add[0]) {
if ($pp[1]) {
$pp[1] .= " $add[0]";
} else {
$pp[1] = $add[0];
}
}
if ($add[1]) {
$pp[1] .= " $add[1]";
}
if ($add[2]) {
$pp[1] .= " $add[2]";
}
ONO::Lib::PDF::Draw->text($canvas,$pdf_x+4, $pdf_y+11+($p*$next_y),$pp[0]);
ONO::Lib::PDF::Draw->text($canvas,$pdf_x+$offset, $pdf_y+11+($p*$next_y),$pp[1],"","","m",(170/$v)-$offset-3);
}
if (($option eq "en" && $tense =~ /^(CON|PCO|PRP)$/) || ($option eq "de" && $tense =~ /^(FUT|PER|PQP)$/)) {
$special++;
my $offset2 = 8;
if ($tense =~ /^(PCO|PRP)$/) {
$offset2 = 11;
}
if ($tense =~ /^(FUT)$/) {
$offset2 = 16;
}
if ($tense =~ /^(PER|PQP)$/) {
$offset2 = 14;
}
my @pp = split(/ /,$VERBCACHE{"$vp[0]_$tense$p"});
$pp[0] =~ s~:(.*)$~~;
ONO::Lib::PDF::Draw->text($canvas,$pdf_x+4, $pdf_y+11+($p*$next_y),$pp[0]);
ONO::Lib::PDF::Draw->text($canvas,$pdf_x+$offset, $pdf_y+11+($p*$next_y),$pp[1]);
ONO::Lib::PDF::Draw->text($canvas,$pdf_x+$offset+$offset2, $pdf_y+11+($p*$next_y),$pp[2]);
}
if ($option eq "fr" && $tense eq "SUBJ") {
$special++;
my @pp = split(/ /,$VERBCACHE{"$vp[0]_$tense$p"});
if ($VERBCACHE{"$vp[0]_$tense$p"} =~ /'/ && $vp[0] !~ /^(s|se)_/) {
# it has to be like this, in 2 lines !
if ($VERBCACHE{"$vp[0]_$tense$p"} =~ /j'/) {
$pp[0] .= " j'";
$pp[1] =~ s~j'~~;
}
} else {
if ($vp[0] =~ /^(s|se)_/ && $pp[0] =~ /il/) {
} else {
$pp[0] = "$pp[0] $pp[1]";
$pp[1] = $pp[2];
if ($pp[3] =~ /[a-z]/) {
$pp[1] .= " $pp[3]";
}
}
}
ONO::Lib::PDF::Draw->text($canvas,$pdf_x+4, $pdf_y+11+($p*$next_y),$pp[0]);
ONO::Lib::PDF::Draw->text($canvas,$pdf_x+8+$offset,$pdf_y+11+($p*$next_y),$pp[1],"","","m",(170/$v)-$offset-11);
}
if (!$special) {
ONO::Lib::PDF::Draw->text($canvas,$pdf_x+4, $pdf_y+11+($p*$next_y),$VERBCACHE{"$vp[0]_$tense$p"});
}
}
}
}
$pdf_x = $pdf_x + 170/$v;
if ($tense_counter%$v == 0) {
$pdf_x = 0;
$pdf_y = $pdf_y + 190/$h;
}
}
# ONO::Lib::PDF::ToolBox->canvas_test($canvas);
}
ONO::FW::Apps::PDF->end;
$WEB .= ONO::FW::Apps::Core->output_paper($pdfkey,\%BLK,\%vars,$HTTP,$BASE);
}
# end of print mode
foreach my $copy (ONO::FW::Apps::Core->unique_copies($vars{'app_input_print_options_unique_copies'})) {
my (@que,@ans,@ans_alt1,@ans_alt2,@ans_alt3,@corr_cache,$first_err_msg);
my ($pdf_x,$pdf_y) = (0,8);
if ($vars{'output_paper'}) {
if ($copy > 1) {
ONO::FW::Apps::PDF->page("",$format);
}
ONO::FW::Apps::Core->headers(\%vars,$format);
ONO::FW::Apps::PDF->title($vars{'app_input_print_options_title'},$PDF_OPTS,$vars{'app_input_print_options_code'},$format);
ONO::FW::Apps::Core->unique_copies_info($canvas,$copy,$vars_ref);
ONO::FW::Apps::Core::Graphics->pdf_draw_item_numbers($canvas,-2,0,1,4,"HV",$vars_ref);
# ONO::Lib::PDF::ToolBox->canvas_test($canvas);
}
if ($vars{'output_web'}) {
$WEB .= qq~<$form>~;
if ($vars{'app_input_multiple_questions_per_page'}) {
($stats_switches,$questions_per_page,$page,$pages) = ONO::FW::Apps::Core->multi_page_logic($page,\%vars);
if ($vars{'app_input_allow_hints'}) {
$stats_switches .= "H";
}
$WEB .= ONO::FW::Apps::Core->stats("",$BLK_ref,"ctm$stats_switches");
$WEB .= ONO::FW::Apps::Core->multi_frame_start($vars{'output_web_finish'});
} else {
if ($vars{'app_input_allow_hints'}) {
$stats_switches .= "H";
}
$WEB .= ONO::FW::Apps::Core->question_progress($vars{'app_input_number_of_questions'},$question_number);
$WEB .= ONO::FW::Apps::Core->stats("",$BLK_ref,"ctmW$stats_switches");
}
}
if (ONO::FW::Apps::Core->question_progress_done($vars{'app_input_number_of_questions'},$question_number) || $vars{'output_web_finish'}) {
$vars{'output_progress_done'}++;
$WEB .= ONO::FW::Apps::Core->question_progress_done_msg($app,$db,$community,$form,$action_url,$vars{'app_input_number_of_questions'},$vars{'output_web_mistakes'},$lang,$BLK_ref,$vars_ref);
} else {
$WEB .= ONO::FW::Apps::Core->timer($vars{'output_web'},$vars{'output_web_timer_start'});
my $SINGLE_QUESTION;
for (my $i = 0; $i < $questions_per_page; $i++) {
# main generator
my $this_verb = $use_verbs[int(rand($use_verb_num))];
my $this_tense = $use_tenses[int(rand($use_tenses_num))];
my $this_person = $use_persons[int(rand($use_pers_num))];
# avoid direct repetitions
my $whilecounter;
while ($cache{'last_verb_used'} eq "$this_verb$this_tense$this_person" && $whilecounter < 8) {
$whilecounter++;
$this_verb = $use_verbs[int(rand($use_verb_num))];
$this_tense = $use_tenses[int(rand($use_tenses_num))];
$this_person = $use_persons[int(rand($use_pers_num))];
}
$cache{'last_verb_used'} = "$this_verb$this_tense$this_person";
# build the vars
my @vp = split(/:/,$this_verb);
my $raw_verb = $vp[0];
my $display_verb = $vp[1];
if ($option eq "en") {
$display_verb = "to $vp[1]";
}
my $display_tense = $use_tenses_names{$this_tense};
my $display_person = $persons[$this_person-1];
$display_person =~ s~\(s\)~ ($SING.)~g;
$display_person =~ s~\(p\)~ ($PLUR.)~g;
# fix bad elles cases (elle/elles can't be used if verb can use both avoir/etre) - step 1 of 2
if ($option eq "fr" && $VERBCACHE{"${raw_verb}_$this_tense$this_person"} =~ /\// && $display_person =~ /^(.*?):(.*?)$/) {
$display_person = $1;
}
my $display_person_alt;
if ($display_person =~ /^(.*?):(.*?)$/) {
if (int(rand(100)) > 50) {
$display_person = $1;
} else {
$display_person_alt = "$1/$2";
$display_person = $2;
}
}
# fix bad elles cases (elle/elles can't be used if verb can use both avoir/etre) - step 2 of 2
if ($option eq "fr" && $VERBCACHE{"${raw_verb}_$this_tense$this_person"} =~ /\// && $display_person =~ /^(.*?):(.*?)$/) {
$display_person = $1;
$display_person_alt = $1;
}
# start special language cases - french
if ($option eq "fr") {
# fix imperatif
if ($this_tense eq "IMPE") {
if ($raw_verb =~ /^(faillir|falloir|neiger|pleuvoir|pouvoir|saillir)$/) {
$this_tense = "IP";
$display_tense = lc $use_tenses_names{$this_tense};
} else {
if ($this_person == 2 || $this_person == 3) {
$this_person = $this_person + 2;
}
if ($this_person == 6) {
$this_person = 1;
}
$display_person = $persons[$this_person-1];
}
}
if ($this_tense eq "IMPE") {
$display_person =~ s~je~sing.~;
$display_person =~ s~nous~1p plur.~;
$display_person =~ s~vous~2p plur.~;
}
# fix participe
if ($this_tense eq "PART_PRES" || $this_tense eq "PART_PASSE") {
$this_person = "";
$display_person = "X";
}
# fix special verb: falloir, pleuvoir, neiger
if ($raw_verb eq "falloir" || $raw_verb eq "pleuvoir" || $raw_verb eq "neiger") {
$this_person = 3;
$display_person = "il";
$display_person_alt = "";
if ($this_tense eq "PART_PRES" || $this_tense eq "PART_PASSE" || $this_tense eq "IMPE") {
# part_passe exists, but doesn't work for an unknown reason, so we'll disable it
$this_tense = "IP";
}
}
}
# start special language cases - german
if ($option eq "de") {
# fix non-prs
if ($this_tense ne "PRS") {
if ($raw_verb =~ /^(moechten)$/) {
$this_tense = "PRS";
$display_tense = $use_tenses_names{$this_tense};
}
}
# fix imperativ
if ($this_tense eq "IMPE") {
if ($raw_verb =~ /^(moechten|koennen|muessen)$/) {
$this_tense = "PRS";
$display_tense = $use_tenses_names{$this_tense};
} else {
if ($this_person == 2) {
$this_person = 1;
}
if ($this_person == 3) {
$this_person = $this_person + 2;
}
$display_person = $persons[$this_person-1];
if ($this_person == 1) {
$display_person = $persons[1];
}
}
}
}
# start special language cases - english
if ($option eq "en") {
}
# end of special language cases
my $verb_id = "${raw_verb}_$this_tense$this_person";
if ($vars{'output_web'}) {
$stat_todo++;
if ($vars{'app_input_multiple_questions_per_page'}) {
if ($vars{'output_web_next_page'}) {
$vars{"output_web_answer_$i"} = "";
} else {
if ($vars{"output_web_cache_que1_$i"}) {
$display_verb = $vars{"output_web_cache_que1_$i"};
}
if ($vars{"output_web_cache_que2_$i"}) {
$display_tense = $vars{"output_web_cache_que2_$i"};
}
if ($vars{"output_web_cache_que3_$i"}) {
$display_person = $vars{"output_web_cache_que3_$i"};
}
if ($vars{"output_web_cache_ans_$i"}) {
$ans[$i] = $vars{"output_web_cache_ans_$i"};
}
if ($vars{"output_web_cache_ans_alt1_$i"}) {
$ans_alt1[$i] = $vars{"output_web_cache_ans_alt1_$i"};
}
if ($vars{"output_web_cache_ans_alt2_$i"}) {
$ans_alt2[$i] = $vars{"output_web_cache_ans_alt2_$i"};
}
if ($vars{"output_web_cache_ans_alt3_$i"}) {
$ans_alt3[$i] = $vars{"output_web_cache_ans_alt3_$i"};
}
}
} else {
$vars{"output_web_answer"} = &clean_answer("",$vars{"output_web_answer"});
$vars{"output_web_answer_feedback"} = $vars{"output_web_answer"};
if (ONO::IO->devstation) {
$WEB .= qq~DevStation: $vars{"output_web_answer"} ne $vars{"output_web_cache_ans_$i"}~;
}
if ($vars{"output_web_answer"} ne "") {
my $special_impe_correct = &special_impe_correct("",$vars{"output_web_answer"},$vars{"output_web_cache_ans_$i"},$vars{"output_web_cache_ans_alt1_$i"});
if (
lc $vars{"output_web_answer"} ne lc $vars{"output_web_cache_ans_$i"} &&
lc $vars{"output_web_answer"} ne lc $vars{"output_web_cache_ans_alt1_$i"} &&
lc $vars{"output_web_answer"} ne lc $vars{"output_web_cache_ans_alt2_$i"} &&
lc $vars{"output_web_answer"} ne lc $vars{"output_web_cache_ans_alt3_$i"} &&
!$special_impe_correct
) {
$vars{'output_web_answer_status'} = 2;
$vars{'output_web_mistakes'}++;
} else {
$question_number++;
$vars{'output_web_answer_status'} = 1;
$vars{'output_web_answer'} = "";
}
}
if (!$vars{'output_web_continue_key'}) {
if ($vars{"output_web_cache_que1_$i"}) {
$display_verb = $vars{"output_web_cache_que1_$i"};
}
if ($vars{"output_web_cache_que2_$i"}) {
$display_tense = $vars{"output_web_cache_que2_$i"};
}
if ($vars{"output_web_cache_que3_$i"}) {
$display_person = $vars{"output_web_cache_que3_$i"};
}
if ($vars{"output_web_cache_ans_$i"}) {
$ans[$i] = $vars{"output_web_cache_ans_$i"};
}
if ($vars{"output_web_cache_ans_alt1_$i"}) {
$ans_alt1[$i] = $vars{"output_web_cache_ans_alt1_$i"};
}
if ($vars{"output_web_cache_ans_alt2_$i"}) {
$ans_alt2[$i] = $vars{"output_web_cache_ans_alt2_$i"};
}
if ($vars{"output_web_cache_ans_alt3_$i"}) {
$ans_alt3[$i] = $vars{"output_web_cache_ans_alt3_$i"};
}
}
}
}
# output paper
if ($vars{'output_paper'}) {
my $verb_width = ONO::Lib::PDF::Draw->string_width($raw_verb,'HB');
my $display_tense_person = $display_tense;
if ($display_person ne "X") {
$display_tense_person .= ", $display_person";
}
if ($option eq "de") {
$display_tense_person =~ s~plusquamperfekt~plusquamp.~;
$display_tense_person =~ s~ / präteritum~~;
}
if ($option eq "en") {
$verb_width = $verb_width + 5;
$display_tense_person =~ s~(present|past) continuous~$1 cont.~;
$display_tense_person =~ s~(present|past|conditional) perfect~$1 perf.~;
}
$corr_cache[$i] = "$verb_id\^$display_verb\^$verb_width\^$display_tense_person\^$display_person_alt\^$ans[$i]\^$pdf_x\^$pdf_y\^";
ONO::Lib::PDF::Draw->font('HB');
ONO::Lib::PDF::Draw->text($canvas,$pdf_x+5, $pdf_y, "$display_verb");
ONO::Lib::PDF::Draw->font('HO');
ONO::Lib::PDF::Draw->text($canvas,$pdf_x+5+$verb_width, $pdf_y, " - $display_tense_person");
ONO::Lib::PDF::Draw->font('',9);
ONO::Lib::PDF::Draw->text($canvas,$pdf_x+75, $pdf_y, "............................................................................................................");
ONO::Lib::PDF::Draw->font('',12);
$pdf_y = $pdf_y + 8;
if (($i+1)%5 == 0) {
$pdf_y = $pdf_y + 7.5;
}
}
if ($vars{'output_web'}) {
# in single-question mode we'll need to load the verb data now
if (!$vars{'app_input_multiple_questions_per_page'}) {
foreach my $line (ONO::IO->list_raw("$VERBDIR/verbs/verb_$raw_verb.txt")) {
my @lp = split(/\^/,$line);
$line =~ s~(\n|\r|\t)~~g;
if ($lp[0] && $lp[1]) {
$lp[1] =~ s~(\<|\>)~~g;
$VERBCACHE{"$vp[0]_$lp[0]"} = $lp[1];
}
}
if ($option eq "de") {
%VERBCACHE = (%VERBCACHE,&german_verb_builder("",$raw_verb,$VERBCACHE{"${raw_verb}_HILF_VERB"},$vp[1],$VERBCACHE{"$vp[0]_PART_PERF"}));
}
}
# build and cache everything
if (!$ans[$i]) {
$ans[$i] = $VERBCACHE{$verb_id};
# alt person (1 - colon - special case if generated, used by german verbs)
if ($ans[$i] =~ s~^(.*?):(.*?) ~~) {
my $opt1 = $1;
my $opt2 = $2;
if ($display_person_alt =~ /\//) {
$ans[$i] = "$opt2 $ans[$i]";
} else {
$ans[$i] = "$opt1 $ans[$i]";
}
}
# alt person (2 - global/general, for all languages)
if ($display_person_alt =~ /\//) {
my @dp = split(/\//,$display_person_alt);
$ans[$i] =~ s~$dp[0] ~$dp[1] ~;
$ans[$i] =~ s~ \((sing\.|plur\.)\)~~gi;
}
# french special case: "elle/elles est/sont" needs to add "e/es" in some cases
# this same code can also be found in the print option !!!
if ($option eq "fr") {
$ans[$i] = &french_elle("",$ans[$i]);
# fix : remove elle/elles if avoir+etre
if ($VERBCACHE{$verb_id} =~ /\//) {
$ans[$i] =~ s/^elle/il/;
$ans_alt1[$i] =~ s/^elle/il/;
$ans_alt2[$i] =~ s/^elle/il/;
$ans_alt3[$i] =~ s/^elle/il/;
$display_person =~ s/^elle/il/;
$display_person_alt =~ s/^elle/il/;
}
}
}
# clean up answer
$ans[$i] =~ s~ ~ ~g;
if ($ans[$i] =~ m~\((.*?)\)~) {
$ans_alt1[$i] = $ans[$i];
$ans_alt1[$i] =~ s~\((.*?)\)~~;
$ans[$i] =~ s~(\(|\))~~g;
}
# the following allows two different answers to be correct (encoded as "answer1/answer2" in the DB)
# note that the app will currently always display "answer1" when answered correctly,
# even if the user opted for "answer2"
if ($ans[$i] =~ m~^(.*?)/(.*?)$~) {
$ans[$i] = $1;
$ans_alt3[$i] = $2;
if ($option eq "fr") {
$ans[$i] = &french_elle("",$ans[$i]);
$ans_alt3[$i] = &french_elle("",$ans_alt3[$i]);
if ($ans[$i] =~ /^elle/) {
$ans_alt3[$i] =~ s~^il~elle~;
if ($ans_alt3[$i] =~ /(elle|elles) (a|ont) /) {
$ans_alt3[$i] = qq~$1 $2 $VERBCACHE{"${raw_verb}_PART_PASSE"}~;
}
}
}
}
if ($vars{'output_web_answer_status'} != 1) {
$WEB .= qq~<input type="hidden" name="output_web_cache_que1_$i" value="$display_verb">
<input type="hidden" name="output_web_cache_que2_$i" value="$display_tense">
<input type="hidden" name="output_web_cache_que3_$i" value="$display_person">
<input type="hidden" name="output_web_cache_ans_$i" value="$ans[$i]">
<input type="hidden" name="output_web_cache_ans_alt1_$i" value="$ans_alt1[$i]">
<input type="hidden" name="output_web_cache_ans_alt2_$i" value="$ans_alt2[$i]">
<input type="hidden" name="output_web_cache_ans_alt3_$i" value="$ans_alt3[$i]">
~;
}
if (!$vars{'app_input_multiple_questions_per_page'}) {
my $TENSE = $display_tense;
if ($display_person ne "X") {
$TENSE .= qq~, <span class="bold">$display_person</span>~;
}
$SINGLE_QUESTION = qq~<span class="bold">$display_verb</span>, <span class="italic">$TENSE</span>~;
} else {
my ($BG,$is_correct);
my $PLA = "?";
if (ONO::IO->devstation) {
$PLA = $ans[$i];
}
$vars{"output_web_answer_$i"} = &clean_answer("",$vars{"output_web_answer_$i"});
my $FIELD = qq~<input type="text" id="output_web_answer_${i}_id" name="output_web_answer_$i" value="$vars{"output_web_answer_$i"}"
maxlength="64" class="w95" placeholder="$PLA" autocomplete="off">~;
my $HINT;
if ($vars{'app_input_allow_hints'}) {
$HINT = qq~<a href="javascript:void(0);" onclick="hint('$i');" class="col3">
<div class="rel" style="top:4px;left:4px">
<div class="block20 bg_dark radius20 abs" style="top:0px;left:0px">
<img class="block16 abs" src="/ono/osr/images/icons/crystal/16x16/apps/ktip.png" style="top:2px;left:2px" alt="">
</div>
<div id="output_web_hints_counter_$i" class="small mr5 abs" style="top:-6px;left:21px">$vars{"output_web_hints_$i"}</div>
</div>
</a>
<input type="hidden" id="output_web_hints_$i" name="output_web_hints_$i" value="$vars{"output_web_hints_$i"}">
<input type="hidden" id="output_web_correct_${i}" name="output_web_correct_${i}" value="$ans[$i]">
~;
}
if ($vars{"output_web_answer_$i"} =~ /[A-Za-z]/) {
$vars{"output_web_answer_$i"} =~ s~‘~'~gi;
$vars{"output_web_answer_$i"} =~ s~' ~'~gi;
$vars{"output_web_answer_$i"} =~ s~ '~'~gi;
# FR: add 'en ' if missing in part_pres
if ($option eq "fr" && $ans[$i] =~ /^en /) {
if ($vars{"output_web_answer_$i"} !~ /^en /) {
$vars{"output_web_answer_$i"} = qq~en $vars{"output_web_answer_$i"}~;
}
}
$BG = " bg_red";
$stat_todo--;
my $special_impe_correct;
if ($option eq "de" && $this_tense eq "IMPE") {
$special_impe_correct = &special_impe_correct("",$vars{"output_web_answer_$i"},$ans[$i],$ans_alt1[$i]);
foreach my $opt ('du','ihr','sie') {
my $Opt = ucfirst $opt;
$vars{"output_web_answer_$i"} =~ s~ $Opt$~ $opt~;
$ans[$i] =~ s~ $Opt$~ $opt~;
$ans_alt1[$i] =~ s~ $Opt$~ $opt~;
$ans_alt2[$i] =~ s~ $Opt$~ $opt~;
$ans_alt3[$i] =~ s~ $Opt$~~;
}
}
if (
$vars{"output_web_answer_$i"} eq $ans[$i] ||
$vars{"output_web_answer_$i"} eq $ans_alt1[$i] ||
$vars{"output_web_answer_$i"} eq $ans_alt2[$i] ||
$vars{"output_web_answer_$i"} eq $ans_alt3[$i] ||
$special_impe_correct
) {
$BG = " bg_green";
# we will now display the user answer instead of the DB entry
# my $ANS = $ans[$i];
# if ($option eq "de" && $this_tense eq "IMPE") {
# $ANS =~ s~ du ~ \(du\) ~;
# }
#
my $ANS = $vars{"output_web_answer_$i"};
$FIELD = qq~<div class="bold green">$ANS</div><input type="hidden" name="output_web_answer_$i" value="$vars{"output_web_answer_$i"}">~;
$stat_correct++;
$is_correct++;
} else {
$stat_wrong++;
$vars{'output_web_mistakes'}++;
if (!$first_err_msg && $display_person && $display_person ne "X") {
my $display_person_first = substr($display_person,0,1);
if ($vars{"output_web_answer_$i"} !~ /^$display_person/ && $vars{"output_web_answer_$i"} !~ /^$display_person_first\'/) {
$first_err_msg++;
my $err = $err_prono;
$err =~ s~###~$display_person~;
$FIELD .= qq~<div id="verbs_err_msg_hint" class="abs">
<div class="box_yellow bo_dark radius10 pad10_2 rel" style="top:-5px;left:10px;z-index:999">
<table class="default_table">
<tr>
<td><img class="block20" src="/ono/osr/images/icons/crystal/32x32/ono/help.png" alt=""></td>
<td>$err</td>
<td><a href="javascript:void(0)"; onclick="onojs_hide('verbs_err_msg_hint');" class="button_green button_mini ml5">$BLK{'ok'}!</a></td>
</tr>
</table>$vars{"output_web_answer_$i"}
</div>
</div>
~;
}
}
}
}
if (!$is_correct && !$focus_on) {
$FIELD .= qq~<script>document.getElementById('output_web_answer_${i}_id').focus();</script>~;
$focus_on++;
}
my $TENSE = $display_tense;
if (!$TENSE) {
$TENSE = qq~Ind.~;
}
if ($display_person ne "X") {
$TENSE .= qq~, <span class="bold">$display_person</span>~;
}
$WEB .= qq~<tr class="bt bb$BG">
<td class="w50 pad10_2 tar small">
<div class="lh125"><span class="bold">$display_verb</span>, <span class="italic">$TENSE :</span></div>
</td>
<td class="w50 p0">$FIELD</td>
<td><div class="block32">$HINT</div></td>
</tr>
~;
}
if ($i == 9) {
$WEB .= ONO::FW::Apps::Core->multi_frame_split;
}
}
}
if ($vars{'output_web'}) {
$WEB .= ONO::FW::Apps::Core->multi_frame_end($vars{'output_web_finish'},$vars{'app_input_multiple_questions_per_page'});
$WEB .= ONO::FW::Apps::Core->input_vars(\%vars);
if ($questions_per_page == 1) {
$WEB .= qq~<div class="lh125 xlarge center rel" style="top:40px">$SINGLE_QUESTION</div>~;
my $CORRECT;
if ($vars{'output_web_answer_status'} == 1) {
# $CORRECT = qq~<td class="bold green">$ans[0]</td>~;
$CORRECT = qq~<td class="bold green">$vars{'output_web_answer_feedback'}</td>~;
}
my $HINT;
if ($vars{'app_input_allow_hints'} && $vars{'output_web_answer_status'} != 1) {
$HINT = qq~<td>
<a href="javascript:void(0);" onclick="hint('0');" class="col3">
<div class="rel small" style="width:24px;top:-8px;left:4px">
<div class="block20 bg_dark radius20 abs" style="top:0px;left:0px">
<img class="block16 abs" src="/ono/osr/images/icons/crystal/16x16/apps/ktip.png" style="top:2px;left:2px" alt="">
</div>
<div id="output_web_hints_counter_0" class="small mr5 abs" style="top:-18px;left:18px">$vars{"output_web_hints_0"}</div>
</div>
</a>
<input type="hidden" id="output_web_hints_0" name="output_web_hints_0_special_transmit" value="$vars{"output_web_hints_0"}">
<input type="hidden" id="output_web_correct_0" name="output_web_correct_0_dont_transmit" value="$ans[0]">
</td>
~;
$WEB .= ONO::FW::Apps::Core->hint_script_v2("length/2","(length/3*2)+1",$vars{'output_web_hints'},"output_web_answer_id");
}
$WEB .= ONO::FW::Apps::Core->check_single(
$CORRECT,
$HINT,
320,
64,
$BLK_ref,
\%vars,
"C",
);
if (ONO::IO->devstation) {
$WEB .= qq~<div class="box_paper center">DEBUG: $ans[0], $ans_alt1[0], $ans_alt2[0], $ans_alt3[0]</div>~;
}
} else {
$WEB .= ONO::FW::Apps::Core->check_multi($BLK_ref,$stat_todo+$stat_wrong,$page,$pages,"",\%vars);
if ($vars{'app_input_allow_hints'}) {
$WEB .= ONO::FW::Apps::Core->hint_script_v2("length/2","(length/3*2)+1",$vars{'output_web_hints'});
}
}
$WEB .= qq~</form>~;
}
}
if (ONO::FW::Apps::Core->print_corrections("$BASE/pdf/pdf-$pdfkey-corr.pdf","",$format,$vars_ref)) {
ONO::FW::Apps::Core->headers(\%vars,$format,"c");
ONO::FW::Apps::PDF->title($BLK{'Corrections'},$PDF_OPTS,$vars{'app_input_print_options_code'},$format);
ONO::FW::Apps::Core->unique_copies_info($canvas,$copy,$vars_ref);
ONO::FW::Apps::Core::Graphics->pdf_draw_item_numbers($canvas,-2,0,1,4,"CHV",$vars_ref);
# ONO::Lib::PDF::ToolBox->canvas_test($canvas);
for (my $c = 0; $c < $questions_per_page; $c++) {
my ($verb_id,$display_verb,$verb_width,$display_tense_person,$display_person_alt,$answer,$pdf_x,$pdf_y) = split(/\^/,$corr_cache[$c]);
my $ANSWER = $VERBCACHE{$verb_id};
if ($display_person_alt =~ /\//) {
my @dp = split(/\//,$display_person_alt);
$ANSWER =~ s~$dp[0] ~$dp[1] ~;
$ANSWER =~ s~ \((sing\.|plur\.)\)~~gi;
}
$ANSWER =~ s~:(sie)~~g;
$ANSWER =~ s~ ~ ~g;
if ($option eq "de") {
if ($display_tense_person =~ /sie \(sing\.\)/i) {
$ANSWER =~ s~^er ~sie ~;
}
}
if ($option eq "fr") {
$ANSWER = &french_elle("",$ANSWER);
}
ONO::Lib::PDF::Draw->font('HB');
ONO::Lib::PDF::Draw->text($canvas,$pdf_x+5, $pdf_y, "$display_verb");
ONO::Lib::PDF::Draw->font('HO');
ONO::Lib::PDF::Draw->text($canvas,$pdf_x+5+$verb_width, $pdf_y, " - $display_tense_person");
ONO::Lib::PDF::Draw->font('H');
ONO::Lib::PDF::Draw->text($canvas,$pdf_x+75, $pdf_y, $ANSWER);
}
}
}
if ($vars{'output_web'}) {
($stat_correct,$stat_todo_total) = ONO::FW::Apps::Core->stats_multi_pages($vars{'app_input_number_of_questions'},$stat_correct,$stat_wrong,$page,$pages);
if ($questions_per_page == 1) {
# if ($vars{'output_web_hints_0_special_transmit'}) {
# $vars{'output_web_hints'} = $vars{'output_web_hints'} + $vars{'output_web_hints_0_special_transmit'};
# }
$stat_correct = $question_number-1;
$WEB = ONO::FW::Apps::Core->stats_replace(
$WEB,$stat_correct,$stat_wrong,$stat_todo_total-$stat_correct,
$vars{'output_web_mistakes'},1,1,$vars{'output_web_completed'},$vars{'output_web_hints_single'},
);
} else {
$WEB = ONO::FW::Apps::Core->stats_replace(
$WEB,$stat_correct,$stat_wrong,$stat_todo_total,$vars{'output_web_mistakes'},$page,$pages,$vars{'output_web_completed'},$vars{'output_web_hints'}
);
}
}
if ($vars{'output_paper'}) {
ONO::FW::Apps::PDF->end;
$WEB .= ONO::FW::Apps::Core->output_paper($pdfkey,\%BLK,\%vars,$HTTP,$BASE);
}
}
my ($status,$WEB) = ONO::Lib::Parser->parse($WEB,$vars_ref);
$WEB .= ONO::FW::Apps::Core->vardump($vars_ref);
$WEB = ONO::FW::Edu::Apps::ToolBox->apps_gate($WEB,$vars_ref);
return $WEB;
} else {
if (!$option) {
return qq~<table class="wide_table">
<tr class="vtop">
<td class="w33 p10">
<a href="$BASE/cgi-bin/local/perl/school/apps/verbs_english.pl?app_lang=$vars{'app_lang'}">
<div class="rel auto" style="width:128px">
<img class="app128" src="/images/apps/verbs_english_128.png" alt="">
<div class="abs app128_inset" style="top:0px"></div>
</div>
</a>
<div class="center mt10">
<a href="$BASE/cgi-bin/local/perl/school/apps/verbs_english.pl?app_lang=$vars{'app_lang'}" class="col3">
English Verbs
</a>
</div>
</td>
<td class="w33 p10">
<a href="$BASE/cgi-bin/local/perl/school/apps/verbs_german.pl?app_lang=$vars{'app_lang'}">
<div class="rel auto" style="width:128px">
<img class="app128" src="/images/apps/verbs_german_128.png" alt="">
<div class="abs app128_inset" style="top:0px"></div>
</div>
</a>
<div class="center mt10">
<a href="$BASE/cgi-bin/local/perl/school/apps/verbs_german.pl?app_lang=$vars{'app_lang'}" class="col3">
Deutsche Verben
</a>
</div>
</td>
<td class="w33 p10">
<a href="$BASE/cgi-bin/local/perl/school/apps/verbs_french.pl?app_lang=$vars{'app_lang'}">
<div class="rel auto" style="width:128px">
<img class="app128" src="/images/apps/verbs_french_128.png" alt="">
<div class="abs app128_inset" style="top:0px"></div>
</div>
</a>
<div class="center mt10">
<a href="$BASE/cgi-bin/local/perl/school/apps/verbs_french.pl?app_lang=$vars{'app_lang'}" class="col3">
Verbes Français
</a>
</div>
</td>
</tr>
</table>
~;
if ($vars{'output_web'}) {
ONO::FW::Apps::Core->varstore($vars{'username'},$vars{'virclass'},$vars{'anonymous'},\%vars);
}
} else {
#############################################################
# EXERCISE SETUP
#############################################################
if (!$vars{'app_input_number_of_questions'}) {
$vars{'app_input_number_of_questions'} = 20;
}
$WEB .= ONO::FW::Apps::Core->infopics(
"screen:320:50:50::verbs_screenshot_1.jpg",
"sheet:168:180:110:15:verbs_french_sheet_1.jpg",
"sheet:168:40:140:-10:verbs_french_sheet_1.jpg",
);
my ($one_tense_selected,$reset_output_selected);
foreach my $key (keys %vars) {
if ($key =~ /^app_input_tense_use_/ && $vars{$key}) {
$one_tense_selected++;
}
if ($key =~ /^output_add_group_/ && $vars{$key}) {
$reset_output_selected++;
}
}
if (!$one_tense_selected) {
$vars{"app_input_tense_use_$codes[0]"}++;
}
if ($vars{'output_add_verb'} || $vars{'output_add_custom'} || $reset_output_selected) {
$vars{"output_selected"} = 0;
}
my $VERBADD;
if ($vars{'output_add'}) {
$VERBADD = ONO::FW::Apps::Core->lang_verbs_add($db,$community,$option,$lang,$BLK_ref,\%vars);
}
my $person_list = ONO::FW::Apps::Core->lang_verbs_persons_list($option);
my $CONF .= ONO::FW::Apps::ToolBox->conf_input("verbs", $BLK_ref,\%vars,"N",ONO::FW::Apps::Core->lang_verbs_default($option),$VERBADD,$option);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("spacer", $BLK_ref,\%vars);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("persons", $BLK_ref,\%vars,"","123456-ABCDEF",$person_list);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("spacer", $BLK_ref,\%vars);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("tenses", $BLK_ref,\%vars,"",$tenses_ref,$pres_ref,$past_ref,$fut_ref);
my $BUTTONS = "op";
$vars{'output_paper_custom_text'} = "$BLK{'print'}: $BLK{'worksheet'} $BLK{'or'} $BLK{'verb'}";
if ($vars{'output_paper'}) {
$vars{'output_paper_custom_text'} = $BLK{'print_worksheet'};
$vars{'output_paper_add_button'} = "output_print_verbs";
$vars{'output_paper_add_button_color'} = "lightgreen";
$vars{'output_paper_add_button_text'} = $BLK{'verb'};
$vars{'output_paper_add_button_hint'} = $BLK{'print_verb'};
}
# if ($vars{'output_print_verbs'}) {
# $BUTTONS = "P";
# }
$WEB .= ONO::FW::Apps::Core->conf_box(
$db,
$community,
$app,
$form,
"",
$action_url,
$CONF,
$lang,
$BLK_ref,
\%vars,
"${BUTTONS}ncdi-CDI-lsu-NO-H",
);
$WEB .= ONO::FW::Apps::Core->info_display(
ONO::FW::Apps::Core->info("info_online_print",$vars{'app_lang'}),
ONO::FW::Apps::Core->info("info_indiv_diff", $vars{'app_lang'}),
);
my ($status,$WEB) = ONO::Lib::Parser->parse($WEB,$vars_ref);
$WEB .= ONO::FW::Apps::Core->vardump($vars_ref,"<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>");
$WEB = ONO::FW::Edu::Apps::ToolBox->apps_gate($WEB,$vars_ref);
return $WEB;
}
}
}
sub clean_answer {
my $answer = $_[1];
$answer =~ s~(\!|\?)~~g;
return ONO::Lib::Basic->remove_bad_spaces($answer);
}
sub german_verb_builder {
my (
$self,
$verb,
$helper,
$verb_name,
$part_perf,
) = @_;
my %ADD;
my @persons = ONO::FW::Apps::Core->lang_verbs_persons('de');
my @h0 = ('', 'werde', 'wirst', 'wird', 'werden', 'werdet', 'werden' );
my @h1 = ('', 'habe', 'hast', 'hat', 'haben', 'habt', 'haben' );
my @h2 = ('', 'hatte', 'hattest', 'hatte', 'hatten', 'hattet', 'hatten' );
my @h3 = ('', 'bin', 'bist', 'ist', 'sind', 'seid', 'sind' );
my @h4 = ('', 'war', 'warst', 'war', 'waren', 'wart', 'waren' );
my @help0 = @h0;
my @help1 = @h1;
my @help2 = @h2;
if ($helper eq "sein") {
@help1 = @h3;
@help2 = @h4;
}
# if ($helper eq "sein/haben" || $helper eq "haben/sein") {
# @help1 = ('', 'habe/bin', 'hast/bist', 'hat/ist', 'haben/sind', 'habt/seid', 'haben/sind' );
# @help2 = ('', 'hatte/war', 'hattest/warst', 'hatte/war', 'hatten/waren', 'hattet/wart', 'hatten/waren' );
# }
my @sich = ('', 'mich', 'dich', 'sich', 'uns', 'euch', 'sich' );
for (my $i = 1; $i < 7; $i++) {
$persons[$i-1] =~ s~\((s|p)\)~~;
$ADD{"${verb}_FUT$i"} = "$persons[$i-1] $help0[$i] $verb_name";
$ADD{"${verb}_PER$i"} = "$persons[$i-1] $help1[$i] $part_perf";
$ADD{"${verb}_PQP$i"} = "$persons[$i-1] $help2[$i] $part_perf";
if ($helper eq "sein/haben" || $helper eq "haben/sein") {
$ADD{"${verb}_PER$i"} = "$persons[$i-1] $h1[$i] $part_perf/$persons[$i-1] $h3[$i] $part_perf";
$ADD{"${verb}_PQP$i"} = "$persons[$i-1] $h2[$i] $part_perf/$persons[$i-1] $h4[$i] $part_perf";
}
if ($verb_name =~ /^sich /) {
my $part_perf_simple = $part_perf;
$part_perf_simple =~ s~^sich ~~;
$ADD{"${verb}_FUT$i"} =~ s~ sich ~ $sich[$i] ~;
$ADD{"${verb}_PER$i"} = "$persons[$i-1] $help1[$i] $sich[$i] $part_perf_simple";
$ADD{"${verb}_PQP$i"} = "$persons[$i-1] $help2[$i] $sich[$i] $part_perf_simple";
}
}
return %ADD;
}
sub french_elle {
my $data = $_[1];
if (($data =~ /^elle est / || $data =~ /^elle s'est /) && $data =~ /(i|u|é)$/) {
$data .= "e";
}
if (($data =~ /^elles sont / || $data =~ /^elles se sont /) && $data =~ /(i|u|é)$/) {
$data .= "es";
}
if (($data =~ /^elles sont / || $data =~ /^elles se sont /) && $data =~ /(i|u|é)s$/) {
$data =~ s/(i|u|é)s$/${1}es/;
}
return $data;
}
sub special_impe_correct {
my (
$self,
$answer,
$special1,
$special2,
) = @_;
my $special_impe_correct;
$answer = lc $answer;
$special1 = lc $special1;
$special2 = lc $special2;
my $special3 = lc $special1;
my $special4 = lc $special2;
$special1 =~ s~ \(du\)( |)~ ~g;
$special2 =~ s~ \(du\)( |)~ ~g;
$special3 =~ s~e \(du\)( |)~ ~g;
$special4 =~ s~e \(du\)( |)~ ~g;
$special1 =~ s~ du( |)~ ~g;
$special2 =~ s~ du( |)~ ~g;
$special3 =~ s~e du( |)~ ~g;
$special4 =~ s~e du( |)~ ~g;
$special4 =~ s~\(~~g;
$special4 =~ s~\)~~g;
$special1 =~ s~ ~ ~g;
$special2 =~ s~ ~ ~g;
$special3 =~ s~ ~ ~g;
$special4 =~ s~ ~ ~g;
$special1 =~ s~ $~~g;
$special2 =~ s~ $~~g;
$special3 =~ s~ $~~g;
$special4 =~ s~ $~~g;
my $reduced_answer = $answer;
$reduced_answer =~ s~ du$~~i;
if ($answer eq $special1 || $answer eq $special2 || $reduced_answer eq $special1 || $reduced_answer eq $special2) {
$special_impe_correct++;
}
if ($answer eq $special3 || $answer eq $special4 || $reduced_answer eq $special3 || $reduced_answer eq $special4) {
$special_impe_correct++;
}
return $special_impe_correct;
}
###################################################################
#### THAT'S IT :-D
###################################################################
1;
__END__