package ONO::FW::Edu::Apps::Modules::MathSteps;
################################################################################
# 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::IO;
use ONO::Lib::Basic;
use ONO::FW::Edu::Apps::ToolBox;
use ONO::FW::Edu::Apps::Modules::WorksheetMaker::Input;
use ONO::FW::Apps::PDF;
use ONO::FW::Apps::ToolBox;
use ONO::Lib::Image::HTML::Arrow;
use ONO::Lib::PDF::Draw;
use ONO::Lib::PDF::ToolBox;
use ONO::Lib::UI::Check;
use ONO::Lib::UI::Select;
use ONO::FW::Apps::Core;
use ONO::FW::Apps::Core::Graphics;
use ONO::Lib::Parser;
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 = "math_steps";
ONO::FW::Apps::Core->now("",$app,$vars{'app_lang'});
my @txt = (
"Calculation steps",
"arrows",
"boxes",
"examples",
"display steps",
"calculate everything",
"steps must be filled out",
"avoid zero values if possible",
"cross the tens barrier",
"don't cross the tens barrier",
);
if ($vars{'app_lang'} eq "de") {
@txt = (
"Rechenschritte",
"Pfeile",
"Kästchen",
"Beispiele",
"Zwischenschritte anzeigen",
"alles rechnen",
"Schritte müssen ausgefüllt werden",
"Nullwerte wenn möglich meiden",
"mit Zehnerüberschreitung",
"keine Zehnerüberschreitung",
);
}
if ($vars{'app_lang'} eq "lu") {
@txt = (
"Recheschrëtt",
"Pfeiler",
"Këschten",
"Beispiller",
"Zwëscheschrëtt uweisen",
"alles rechnen",
"Schrëtt mussen ausgefëllt ginn",
"Nullwerter wa méiglech évitéieren",
"mat Zehnerüberschreitung",
"keng Zehnerüberschreitung",
);
}
if ($vars{'app_lang'} eq "fr") {
@txt = (
"Calcul en étapes",
"flèches",
"boites",
"exemples",
"afficher étapes",
"tout calculer",
"étapes doivent être remplies",
"éviter zéros si possible",
"dépasser les dixaines",
"ne pas dépasser les dixaines",
);
}
my $WEB;
$WEB .= ONO::FW::Apps::Core->output_paper_save($pdfkey,$BLK_ref,\%vars,$HTTP,$BASE,"$year$mon$mday");
if (ONO::FW::Apps::Core->running(\%vars,$db)) {
$WEB .= ONO::FW::Apps::Core->blockbackbutton($BASE,$vars_ref);
#############################################################
# WORKSHEET MAKER
#############################################################
if ($vars{'output_worksheet_maker'}) {
$vars_ref = ONO::FW::Edu::Apps::Modules::WorksheetMaker::Input->vars(\%vars);
%vars = %$vars_ref;
}
#############################################################
# ONLINE TRAINING
#############################################################
$vars{'app_input_op_mul'} = 0;
$vars{'app_input_op_div'} = 0;
if ($vars{'output_web'} || $vars{'output_paper'}) {
my $question_number = ONO::FW::Apps::Core->question_number($vars{'output_web_question_number'});
if ($vars{'output_web_cache_next'}) {
$question_number++;
$vars{'output_web_question_number'}++;
}
my ($page,$pages,%cache,$whilecounter,$stats_switches,$PDF_OPTS);
my ($stat_correct,$stat_wrong,$stat_todo,$stat_todo_total);
my $questions_per_page = 1;
$vars{'app_input_op_mul'} = 0;
$vars{'app_input_op_div'} = 0;
if (!$vars{'app_input_type_arrows'} && !$vars{'app_input_type_boxes'} && !$vars{'app_input_type_rows'}) {
$vars{'app_input_type_arrows'} = 1;
}
for (my $a = 1; $a < 4; $a++) {
if ($vars{"app_input_autofill_$a"} eq "") {
$vars{"app_input_autofill_$a"} = "none";
}
}
if (!$vars{'app_input_num_of_items_status'}) {
$vars{'app_input_num_of_items_status'} = 24;
}
if ($vars{'app_input_range_from'} > 1000 || $vars{'app_input_range_to'} > 1000) {
$vars{'app_input_range_from'} = 1;
$vars{'app_input_range_to'} = 1000;
}
if ($vars{'app_input_type_rows'}) {
$vars{'app_input_num_of_items_status'} = 24;
}
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 = $vars{'app_input_num_of_items_status'};
}
foreach my $copy (ONO::FW::Apps::Core->unique_copies($vars{'app_input_print_options_unique_copies'})) {
my ($pdf_x,$pdf_y) = (0,0);
my @corr_cache;
my @result_hints;
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,"HlV",\%vars);
# ONO::Lib::PDF::ToolBox->canvas_test($canvas);
}
if ($vars{'output_web'}) {
$WEB .= qq~<$form>~;
$WEB .= ONO::FW::Apps::Core->question_progress($vars{'app_input_number_of_questions'},$question_number);
$WEB .= ONO::FW::Apps::Core->stats("",$BLK_ref,"ctmW");
}
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);
} else {
for (my $i = 0; $i < $questions_per_page; $i++) {
my ($type,$op,$num1,$num2,$res,$step,$s1,$s2);
if ($vars{'output_web_cache_op'} ne "" && $vars{'output_web_cache_num1'} ne "" && $vars{'output_web_cache_num2'} ne "" && $vars{'output_web_cache_res'} ne "" && !$vars{'output_web_cache_next'}) {
$type = $vars{'output_web_cache_type'};
$op = $vars{'output_web_cache_op'};
$num1 = $vars{'output_web_cache_num1'};
$num2 = $vars{'output_web_cache_num2'};
$res = $vars{'output_web_cache_res'};
$step = $vars{'output_web_cache_step'};
$s1 = $vars{'output_web_cache_s1'};
$s2 = $vars{'output_web_cache_s2'};
} else {
if ($vars{'output_web_cache_next'}) {
for (my $n = 0; $n < 6; $n++) {
$vars{"output_web_answer_$n"} = "";
}
}
my $whilecounter;
while ((!$op || $op eq "mul" || $op eq "div") && $whilecounter < 4096) {
$whilecounter++;
$op = ONO::FW::Apps::Core->random_operation(ONO::FW::Apps::Core->get_operations($vars_ref));
}
if ((!$op || $op eq "mul" || $op eq "div")) {
$op = "add";
}
my @types;
foreach my $opt ('arrows','boxes','rows') {
if ($vars{"app_input_type_$opt"}) {
@types = (@types,$opt);
}
}
my $types_num = @types;
$type = $types[int(rand($types_num))];
if (!$type) {
$type = "arrows";
}
# avoid switching types within paragraphs
if ($vars{'output_paper'}) {
my $row = 1+int($pdf_y/47.5);
if ($vars{"type_in_row_$row"}) {
$type = $vars{"type_in_row_$row"};
} else {
$vars{"type_in_row_$row"} = $type;
}
}
# ...
my $num1_min = $vars{'app_input_range_from'};
my $num1_max = $vars{'app_input_range_to'}-10;
if ($op eq "sub") {
if ($vars{'app_input_range_from'} < 10) {
$num1_min = 10;
}
$num1_max = $vars{'app_input_range_to'};
}
my ($whilecounter,$tens_barrier_cracked);
while ($whilecounter < 255 && (
$num1 < $num1_min || $num2 > $num1_max ||
$num2 < $vars{'app_input_range_from'} || $num2 > $vars{'app_input_range_to'} ||
$num2 < 10 || ($vars{'app_input_avoid_zero'} && $num2 =~ /0/) ||
$res < $vars{'app_input_range_from'} || $res > $vars{'app_input_range_to'} ||
($vars{'app_input_num_mode'} < 1 && $tens_barrier_cracked)
)
) {
$whilecounter++;
$tens_barrier_cracked = 0;
if ($op eq "add") {
$res = $vars{'app_input_range_from'}+int(rand($vars{'app_input_range_to'}-$vars{'app_input_range_from'}));
# alt number generator for 100+
if ($vars{'app_input_range_to'} > 100 && $vars{'app_input_num_mode'} =~/(2|3)/) {
$res = int($res/10)*10;
}
$num1 = int(rand($res));
if ($vars{'app_input_range_to'} > 100 && $vars{'app_input_num_mode'} =~/(2|3)/) {
$num1 = int($num1/10)*10;
}
$num2 = $res-$num1;
if ($vars{'app_input_num_mode'} == 3) {
$num1 = $num1+int(rand(10));
$res = $num1+$num2;
}
# alt number generator for 10-
if ($vars{'app_input_num_mode'} == 4) {
$res = 0;
my $whilecounter2;
while ($whilecounter2 < 256 && ($res < 11 || $res > 20)) {
$whilecounter2++;
$num1 = 1+int(rand(9));
$num2 = 1+int(rand(9));
$res = $num1 + $num2;
}
my $pre_num1 = int(($vars{'app_input_range_from'} + rand($vars{'app_input_range_to'}-$vars{'app_input_range_from'}))/10);
if ("$pre_num1$num1" + $num2 < $vars{'app_input_range_to'}+1) {
$num1 = "$pre_num1$num1";
}
$res = $num1 + $num2;
}
# tens checker
if (ONO::Lib::Basic->substr_last_digit($num1) + ONO::Lib::Basic->substr_last_digit($num2) > 9) {
$tens_barrier_cracked++;
}
}
if ($op eq "sub") {
$num1 = $vars{'app_input_range_from'}+int(rand($vars{'app_input_range_to'}-$vars{'app_input_range_from'}));
# alt number generator for 100+
if ($vars{'app_input_range_to'} > 100 && $vars{'app_input_num_mode'} =~/(2|3)/) {
$num1 = int($num1/10)*10;
}
$num2 = int(rand($num1));
if ($vars{'app_input_range_to'} > 100 && $vars{'app_input_num_mode'} =~/(2|3)/) {
$num2 = int($num2/10)*10;
}
$res = $num1-$num2;
if ($vars{'app_input_num_mode'} == 3) {
$num1 = $num1+int(rand(10));
$res = $num1-$num2;
}
# alt number generator for 10-
if ($vars{'app_input_num_mode'} == 4) {
$num1 = 1+int(rand(8));
$num2 = 0;
my $whilecounter2;
while ($whilecounter2 < 256 && ($num2 < $num1+1 || $num2 > 9)) {
$whilecounter2++;
$num2 = 1+int(rand(9));
}
my $pre_num1 = int(($vars{'app_input_range_from'}+rand($vars{'app_input_range_to'}-$vars{'app_input_range_from'}))/10);
if ("$pre_num1$num1" < $vars{'app_input_range_to'}+1) {
$num1 = "$pre_num1$num1";
}
if ($num1 < $num2) {
$num1 = "1$num1";
}
$res = $num1 - $num2;
}
# tens checker
if (ONO::Lib::Basic->substr_last_digit($num1) - ONO::Lib::Basic->substr_last_digit($num2) < 0) {
$tens_barrier_cracked++;
}
}
}
$s1 = int($num2/10)*10;
if ($num2 > 99) {
$s1 = int($num2/100)*100;
}
$s2 = $num2-$s1;
$step = $num1+$s1;
if ($op eq "sub") {
$step = $num1-$s1;
}
if ($vars{'app_input_num_mode'} == 4) {
my $last = substr($num1,(length $num1)-1,1);
$s1 = 10-$last;
$step = $num1 + $s1;
$s2 = $num2 - $s1;
if ($op eq "sub") {
$s1 = $last;
$step = $num1 - $s1;
$s2 = $num2 - $s1;
}
}
}
my @nums = ($num1,$num2,$res,$step,$s1,$s2);
# output paper
if ($vars{'output_paper'}) {
my $size = 1;
my ($large,$off_x,$off_y,$rectify,$lim_y,$i_split);
if ($vars{'app_input_num_of_items_status'} == 24 && $i%2 == 0) {
$pdf_y = $pdf_y + 2.5;
}
if ($vars{'app_input_num_of_items_status'} == 8) {
$large++;
}
if ($vars{'app_input_num_of_items_status'} == 12) {
if ($i =~ /^(0|1|2|5|6|7)$/) {
$large++;
if ($i =~ /^(5|6|7)$/) {
$off_x = 30;
}
}
if ($i =~ /^(3|8)$/) {
$pdf_y = $pdf_y+1;
}
if ($i == 10) {
$pdf_y = 145;
}
}
if ($vars{'app_input_num_of_items_status'} == 16) {
if ($i =~ /^(0|1|6|7)$/) {
$large++;
if ($i =~ /^(6|7)$/) {
$off_x = 30;
}
}
if ($i =~ /^(2|8)$/) {
$pdf_y = $pdf_y+1.5;
}
if ($i =~ /^(4|10|14)$/) {
$pdf_y = $pdf_y+2.5;
}
if ($i == 12) {
$pdf_y = 97,5;
}
}
if ($vars{'app_input_num_of_items_status'} == 20) {
if ($i =~ /^(0|7)$/) {
$large++;
if ($i == 7) {
$off_x = 30;
}
}
if ($i =~ /^(1|8)$/) {
$pdf_y = $pdf_y+2;
}
if ($i =~ /^(3|5|10|12|16|18)$/) {
$pdf_y = $pdf_y+2.5;
}
if ($i == 14) {
$pdf_y = 50;
}
}
if ($type eq "rows") {
$large = 0;
}
if ($large) {
$off_y = 10;
$size = 1.6;
}
if (!$vars{'app_input_result_hints'} || $pdf_x < 10 || $pdf_y < 142.5) {
if ($type eq "boxes" || $type eq "arrows" || $i%2 == 0) {
$corr_cache[$i] = "$pdf_x\^$off_x\^$pdf_y\^$off_y\^$type\^$size\^$op\^$num1\^$num2\^$res\^$step\^$s1\^$s2";
my $autofill;
if ($vars{'app_input_autofill_1'} =~ /^(examples|steps)$/ && $pdf_y < 45) {
$autofill = $1;
}
if ($vars{'app_input_autofill_2'} =~ /^(examples|steps)$/ && $pdf_y > 45 && $pdf_y < 90) {
$autofill = $1;
}
if ($vars{'app_input_autofill_3'} =~ /^(examples|steps)$/ && $pdf_y > 90) {
$autofill = $1;
}
my @nums = ($num1,$num2,"","","","");
if ($autofill eq "examples") {
@nums = ($num1,$num2,$res,$step,$s1,$s2);
} else {
@result_hints = (@result_hints,$res);
}
if ($autofill eq "steps") {
@nums = ($num1,$num2,"","",$s1,$s2);
}
ONO::FW::Apps::Core::Graphics->pdf_draw_stepcalc($canvas,$pdf_x+$off_x,$pdf_y+$off_y,$type,$size,$op,\@nums);
}
}
$pdf_y = $pdf_y + 22.5;
if ($large) {
$pdf_y = $pdf_y + 25.5;
}
if ($pdf_y > 180) {
if ($vars{'app_input_num_of_items_status'} == 8) {
$pdf_x = $pdf_x + 90;
} else {
$pdf_x = $pdf_x + 60;
}
$pdf_y = 0;
$vars{'current_type_reset'}++;
}
}
if ($vars{'output_web'}) {
my $OP_COLOR = "green";
my $OP_SIGN = "+";
my $STEP_ALT = $num1 + $s2;
if ($op eq "sub") {
$OP_COLOR = "red";
$OP_SIGN = "–";
$STEP_ALT = $num1 - $s2;
}
my $BORDER = "border:3px solid #666666;";
my $HEIGHT1 = "height:40px;";
my $HEIGHT2 = "height:36px;";
my @NUMS = ($num1,"$OP_SIGN $num2",$res,$step,$s1,$s2);
# steps can be inverted!
if (
($vars{"output_web_answer_3"} ne "" && $vars{"output_web_answer_3"} == $STEP_ALT) ||
($vars{"output_web_answer_4"} ne "" && $vars{"output_web_answer_4"} == $s2) ||
($vars{"output_web_answer_5"} ne "" && $vars{"output_web_answer_5"} == $s1)
) {
@NUMS = ($num1,"$OP_SIGN $num2",$res,$STEP_ALT,$s2,$s1);
}
my ($BOX,$RES,$FOCUS,$answer_is_correct,$fields_are_correct,@focus_field,$focus_set);
# generate input fields and/or results
for (my $n = 0; $n < 6; $n++) {
$vars{"output_web_answer_$n"} =~ s~[^0-9]~~gi;
if ($n > 1) {
my $ONKEY;
if ($type eq "rows" && ($n == 2 || $n == 3)) {
$ONKEY = qq~ onkeyup="math_steps_val_update('$n');" onkeydown="math_steps_val_update('$n');"~;
}
if ($vars{"output_web_answer_$n"} ne "") {
if ($vars{"output_web_answer_$n"} == $NUMS[$n]) {
my $PAD = "p10";
if ($n == 4 || $n == 5) {
$PAD = "pad10_2";
}
$NUMS[$n] = qq~<div class="$PAD rel">
$vars{"output_web_answer_$n"}
<div class="abs" style="top:24px;left:36px"><img class="block32" src="/ono/osr/images/icons/crystal/32x32/ono/ok.png" alt="correct"></div>
</div>
<input type="hidden" name="output_web_answer_$n" value="$vars{"output_web_answer_$n"}">
~;
$fields_are_correct++;
if ($n == 2) {
$answer_is_correct++;
}
} else {
$NUMS[$n] = qq~<div class="rel">
<input type="text" id="output_web_answer_${n}_id" name="output_web_answer_$n" value="$vars{"output_web_answer_$n"}" class="w100 center" maxlength="4"$ONKEY>
<div class="abs" style="top:-30px;left:36px"><img class="block32" src="/ono/osr/images/icons/crystal/32x32/ono/delete.png" alt="mistake"></div>
</div>
~;
$focus_field[$n]++;
$vars{'output_web_mistakes'}++;
}
} else {
my $PLA;
if (ONO::IO->devstation) {
$PLA = qq~ placeholder="$NUMS[$n]"~;
}
$NUMS[$n] = qq~<input type="text" id="output_web_answer_${n}_id" name="output_web_answer_$n" value="$vars{"output_web_answer_$n"}" class="w100 center" maxlength="4"$PLA$ONKEY>~;
$focus_field[$n]++;
}
} else {
$NUMS[$n] = qq~<div class="p10">$NUMS[$n]</div>~;
}
}
foreach my $focus (4,3,5,2) {
if ($focus_field[$focus] && !$focus_set) {
$focus_set++;
$FOCUS .= qq~onojs_focus('output_web_answer_${focus}_id');~;
}
}
my $BUTTON = qq~<input type="submit" name="do_check" value="$BLK{'check'}" class="button_green button_big mt10">~;
if ($answer_is_correct) {
if (!$vars{'app_input_steps_required'} || $fields_are_correct == 4) {
$RES = qq~<div class="box_green large bold center mt10">$BLK{'Please_wait'}...</div>
<input type="hidden" name="output_web_cache_next" value="1">
<script>onojs_submit();</script>
~;
$BUTTON = "";
}
}
$WEB .= ONO::FW::Apps::Core->input_vars(\%vars);
$WEB .= qq~<input type="hidden" name="output_web_cache_type" value="$type">
<input type="hidden" name="output_web_cache_op" value="$op">
<input type="hidden" name="output_web_cache_num1" value="$num1">
<input type="hidden" name="output_web_cache_num2" value="$num2">
<input type="hidden" name="output_web_cache_res" value="$res">
<input type="hidden" name="output_web_cache_step" value="$step">
<input type="hidden" name="output_web_cache_s1" value="$s1">
<input type="hidden" name="output_web_cache_s2" value="$s2">
~;
if ($type eq "arrows") {
my $ARROW1 = ONO::Lib::Image::HTML::Arrow->curved(235,50,3,30,"666666","s","a");
my $ARROW2 = ONO::Lib::Image::HTML::Arrow->curved(180,50,3,30,"666666","s","a");
$BOX = qq~<div class="rel">
<div class="rel" style="top:35px;left:50px">$ARROW1</div>
<div class="rel" style="top:35px;left:320px">$ARROW2</div>
<div class="rel">
<table class="wide_table mb20">
<tr>
<td class="w20"></td>
<td class="w25">
<div class="box_$OP_COLOR center xlarge bold" style="$BORDER$HEIGHT1">
<table class="default_table">
<tr>
<td>$OP_SIGN</td>
<td>$NUMS[4]</td>
</tr>
</table>
</div>
</td>
<td class="w20"></td>
<td class="w20">
<div class="box_$OP_COLOR center xlarge bold" style="$BORDER$HEIGHT1">
<table class="default_table">
<tr>
<td>$OP_SIGN</td>
<td>$NUMS[5]</td>
</tr>
</table>
</div>
</td>
<td class="w15"></td>
</tr>
</table>
<table class="wide_table">
<tr>
<td class="w20"><div class="box_fabric center xlarge bold" style="$BORDER$HEIGHT1">$NUMS[0]</div></td>
<td class="w25"></td>
<td class="w20"><div class="box_fabric center xlarge bold" style="$BORDER$HEIGHT1">$NUMS[3]</div></td>
<td class="w15"></td>
<td class="w20"><div class="box_fabric center xlarge bold" style="$BORDER$HEIGHT1">$NUMS[2]</div></div></td>
</tr>
</table>
</div>
</div>
~;
}
if ($type eq "boxes") {
my $ARROW1 = ONO::Lib::Image::HTML::Arrow->arrow(320,3,"666666","s","a");
my $ARROW2 = ONO::Lib::Image::HTML::Arrow->curved(450,50,3,30,"cccccc","a","s");
$BOX = qq~<div class="rel">
<div class="box_$OP_COLOR abs rot135" style="top:80px;left:140px;width:100px;$BORDER"></div>
<div class="box_$OP_COLOR abs rot45" style="top:80px;left:285px;width:100px;$BORDER"></div>
<div class="rel" style="top:35px;left:115px">$ARROW1</div>
<div class="rel rot180" style="top:130px;left:-50px">$ARROW2</div>
<div class="rel">
<table class="wide_table mb20">
<tr>
<td class="w20"><div class="box_fabric center xlarge bold nowrap" style="$BORDER$HEIGHT1">$NUMS[0]</div></td>
<td class="w20"></td>
<td class="w20"><div class="box_$OP_COLOR center xlarge bold nowrap" style="$BORDER$HEIGHT1">$NUMS[1]</div></td>
<td class="w20"></td>
<td class="w20"><div class="box_fabric center xlarge bold nowrap" style="$BORDER$HEIGHT1">$NUMS[2]</div></div></td>
</tr>
</table>
<div class="inline w80 auto">
<table class="wide_table">
<tr>
<td class="w10"></td>
<td class="w25">
<div class="box_$OP_COLOR center xlarge bold mb20" style="$BORDER$HEIGHT2">
<table class="default_table">
<tr>
<td>$OP_SIGN</td>
<td>$NUMS[4]</td>
</tr>
</table>
</div>
</td>
<td class="w5"></td>
<td class="w20"><div class="box_fabric center xlarge bold mt20" style="$BORDER$HEIGHT2">$NUMS[3]</div></td>
<td class="w5"></td>
<td class="w25">
<div class="box_$OP_COLOR center xlarge bold mb20" style="$BORDER$HEIGHT2">
<table class="default_table">
<tr>
<td>$OP_SIGN</td>
<td>$NUMS[5]</td>
</tr>
</table>
</div>
</td>
<td class="w10"></td>
</tr>
</table>
</div>
</div>
</div>
~;
}
if ($type eq "rows") {
my $ARROW1 = ONO::Lib::Image::HTML::Arrow->arrow(320,3,"666666","s","a");
my $ARROW2 = ONO::Lib::Image::HTML::Arrow->curved(450,50,3,30,"cccccc","a","s");
my $OP_COLOR2 = "339933";
if ($op eq "sub") {
$OP_COLOR2 = "993333";
}
$BOX = qq~<div class="rel">
<div class="w80 auto">
<table class="wide_table">
<tr>
<td class="p0 w25 bb_dark"><div class="tar xlarge bold nowrap">$NUMS[0]</div></td>
<td class="pad10_2 bb_dark"><div class="xlarge bold"> </div></td>
<td class="p0 w50"><div class="box_$OP_COLOR center xlarge bold nowrap" style="border:5px solid #$OP_COLOR2">$NUMS[1]</div></td>
<td class="pad10_2 bb_dark"><div class="xlarge bold">=</div></td>
<td class="p0 w25 bb_dark"><div class="center xlarge bold nowrap"><span id="math_steps_val_2">?</span></div></div></td>
</tr>
</table>
<table class="wide_table">
<tr>
<td class="w33 tar large bb_dark"><div class="mt10">$NUMS[0]</div></td>
<td class="w33 bg_$OP_COLOR bb_dark">
<div class="box_$OP_COLOR">
<table class="default_table p10 mt10">
<tr>
<td class="large bold">$OP_SIGN</td>
<td> </td>
<td>$NUMS[4]</td>
</tr>
</table>
</div>
</td>
<td class="w33 bb_dark">
<table class="default_table mt10">
<tr>
<td class="pad10_2 large bold">=</td>
<td>$NUMS[3]</td>
</tr>
</table>
</td>
</tr>
<tr>
<td class="tar large bb_dark"><div class="mt10"><span id="math_steps_val_3">?</span> </div></td>
<td class="w33 bg_$OP_COLOR bb_dark">
<div class="box_$OP_COLOR">
<table class="default_table p10 mt10">
<tr>
<td class="large bold">$OP_SIGN</td>
<td> </td>
<td>$NUMS[5]</td>
</tr>
</table>
</div>
</td>
<td class="bb_dark">
<table class="default_table mt10">
<tr>
<td class="pad10_2 large bold">=</td>
<td>$NUMS[2]</td>
</tr>
</table>
</td>
</tr>
<tr>
<td></td>
<td class="p0"><div class="box_$OP_COLOR flat_top"></div></td>
<td></td>
</tr>
</table>
</div>
<script>
function math_steps_val_update(id) {
onojs_sethtml('math_steps_val_'+id,onojs_getvalue('output_web_answer_'+id+'_id'));
}
</script>
</div>
~;
}
my $PRE;
if ($type eq "arrows" || $type eq "boxes") {
$PRE .= qq~ <div class="bb mb20">
<div class="xlarge center mb20">$num1 $OP_SIGN $num2 = ?</div>
</div>
~;
}
$WEB .= qq~<div class="inline auto w66" style="overflow:hidden">
<div class="box_fabric mt20">
<div class="box_paper p20 rel">
$PRE
$BOX
$RES
<script>$FOCUS</script>
</div>
<div class="inline auto">$BUTTON</div>
</div>
</div>
~;
}
}
}
if ($vars{'output_web'}) {
$WEB .= qq~</form>~;
}
if ($vars{'output_paper'} && $vars{'app_input_result_hints'}) {
# ONO::Lib::PDF::Draw->font('H',12);
ONO::FW::Apps::Core::Graphics->pdf_draw_result_hints($canvas,90,144,124,44,6,5,\@result_hints,"En");
}
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,"CHlV",\%vars);
# ONO::Lib::PDF::ToolBox->canvas_test($canvas);
my $corr_count;
foreach my $cache (@corr_cache) {
my ($pdf_x,$off_x,$pdf_y,$off_y,$type,$size,$op,$n0,$n1,$n2,$n3,$n4,$n5) = split(/\^/,$cache);
my @nums = ($n0,$n1,$n2,$n3,$n4,$n5);
if ($type eq "boxes" || $type eq "arrows" || $corr_count%2 == 0) {
ONO::FW::Apps::Core::Graphics->pdf_draw_stepcalc($canvas,$pdf_x+$off_x,$pdf_y+$off_y,$type,$size,$op,\@nums,"B");
}
$corr_count++;
}
}
}
if ($vars{'output_web'}) {
$stat_correct = $question_number - 1;
$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'});
}
if ($vars{'output_paper'}) {
ONO::FW::Apps::PDF->end;
$WEB .= ONO::FW::Apps::PDF->please_wait($pdfkey,\%BLK,\%vars,"",$HTTP,$BASE);
}
}
} else {
#############################################################
# EXERCISE SETUP
#############################################################
if (!$vars{'app_input_number_of_questions'}) {
$vars{'app_input_number_of_questions'} = 20;
if (ONO::IO->device eq "phone") {
$vars{'app_input_number_of_questions'} = 10;
}
}
$WEB .= ONO::FW::Apps::Core->infopics(
"screen:320:50:40::math_steps_screenshot_1.jpg",
"sheet:168:190:140:15:math_steps_sheet_1.jpg",
"sheet:168:40:160:-10:math_steps_sheet_2.jpg",
);
if (!$vars{'app_input_type_arrows'} && !$vars{'app_input_type_boxes'} && !$vars{'app_input_type_rows'}) {
$vars{'app_input_type_arrows'} = 1;
}
if (!$vars{'app_input_num_of_items_status'}) {
$vars{'app_input_num_of_items'} = 16;
$vars{'app_input_num_of_items_status'} = 16;
}
if ($vars{'app_input_autofill_1'} eq "") {
$vars{'app_input_autofill_1'} = "examples";
}
if ($vars{'app_input_autofill_2'} eq "") {
$vars{'app_input_autofill_2'} = "steps";
}
if ($vars{'app_input_autofill_3'} eq "") {
$vars{'app_input_autofill_3'} = "none";
}
my (%setup,@boxes,$CUSTOM1);
@boxes = (
"arrows::/images/morzino/apps/math_steps_box_arrows.png:$txt[1]",
"boxes::/images/morzino/apps/math_steps_box_boxes.png:$txt[2]",
"rows::/images/morzino/apps/math_steps_box_rows.png:$BLK{'rows'}",
);
$CUSTOM1 = ONO::Lib::UI::Select->boxes(
"app_input_type",
\@boxes,
\%vars,
80,
28,
);
my @tabs = ("8:green:8 (4 x 2)","12:green:12","16:green:16","20:green:20","24:green:24 (4 x 6)");
my $CUSTOM2 = ONO::Lib::UI::Select->buttons(
"app_input_num_of_items",
$vars{'app_input_num_of_items_status'},
\@tabs,
"",
"f",
$BLK_ref,
\%setup,
);
my $CONF;
$CONF .= ONO::FW::Apps::ToolBox->conf_input("range", $BLK_ref,\%vars,"",1,100,1000);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("spacer", $BLK_ref,\%vars);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("ops", $BLK_ref,\%vars,"","as-A");
$CONF .= ONO::FW::Apps::ToolBox->conf_input("spacer", $BLK_ref,\%vars,"","");
$CONF .= ONO::FW::Apps::ToolBox->conf_input("custom", $BLK_ref,\%vars,"T",$BLK{'type'},$CUSTOM1);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("spacer", $BLK_ref,\%vars,"","");
if ($vars{'output_paper'}) {
$CONF .= ONO::FW::Apps::ToolBox->conf_input("custom", $BLK_ref,\%vars,"",$BLK{'questions'},$CUSTOM2);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("spacer", $BLK_ref,\%vars,"","");
foreach my $opt ("1:1","2:2","3:3/4") {
my @op = split(/:/,$opt);
my $SEL;
foreach my $opt2 ("examples:$txt[3]","steps:$txt[4]","none:$txt[5]") {
my @op2 = split(/:/,$opt2);
my $sel;
if ($vars{"app_input_autofill_$op[0]"} eq $op2[0]) {
$sel = " selected";
}
$SEL .= qq~<option value="$op2[0]"$sel>$op2[1]</option>~;
}
my $CUSTOM2 = qq~<div class="select_small"><select name="app_input_autofill_$op[0]">$SEL</select></div>~;
$CONF .= ONO::FW::Apps::ToolBox->conf_input("custom", $BLK_ref,\%vars,"",$op[1],$CUSTOM2);
}
$CONF .= ONO::FW::Apps::ToolBox->conf_input("spacer", $BLK_ref,\%vars,"","");
} else {
$CONF .= qq~<input type="hidden" name="app_input_num_of_items_status" value="$vars{"app_input_num_of_items_status"}">~;
for (my $i = 1; $i < 4; $i++) {
$CONF .= qq~<input type="hidden" name="app_input_autofill_$i" value="$vars{"app_input_autofill_$i"}">~;
}
}
my %sel;
$sel{$vars{'app_input_num_mode'}} = " selected";
my $TENS;
$TENS = qq~<div class="select_small"><select id="app_input_num_mode_id" name="app_input_num_mode" onchange="app_input_num_mode_change();">
<option value="1"$sel{'1'}>$txt[8]</option>
<option value="0"$sel{'0'}>$txt[9]</option>
<option value="0">----</option>
<option value="4"$sel{'4'}>$BLK{'up_to'} 10: 35 + 9 = 35 + 5 + 4</option>
<option value="0">----</option>
<option value="2"$sel{'2'}>$BLK{'over'} 100: 320 + 120 = 320 + 100 + 20</option>
<option value="3"$sel{'3'}>$BLK{'over'} 100: 325 + 120 = 325 + 100 + 20</option>
</select></div>
~;
$CONF .= ONO::FW::Apps::ToolBox->conf_input("custom", $BLK_ref,\%vars,"","",$TENS);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("check", $BLK_ref,\%vars,"JS","","avoid_zero",$vars{'app_input_avoid_zero'},$txt[7]);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("resulthints", $BLK_ref,\%vars,"","S");
if ($vars{'output_web'}) {
$CONF .= ONO::FW::Apps::ToolBox->conf_input("check", $BLK_ref,\%vars,"S","","steps_required",$vars{'app_input_steps_required'},$txt[6]);
} else {
$CONF .= qq~<input type="hidden" name="app_input_steps_required" value="$vars{"app_input_steps_required"}">~;
}
$WEB .= ONO::FW::Apps::Core->conf_box(
$db,
$community,
$app,
$form,
"",
$action_url,
$CONF,
$lang,
$BLK_ref,
\%vars,
"op-ncdi-CDI-lsu-N",
);
$WEB .= qq~<script>
function app_input_num_mode_change() {
onojs_class('ono_fwapps_input_row_avoid_zero','');
if (onojs_getvalue('app_input_num_mode_id') == 2) {
onojs_class('ono_fwapps_input_row_avoid_zero','trans30');
}
}
app_input_num_mode_change();
</script>
~;
if (!$vars{'exercise'}) {
$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);
$WEB = ONO::FW::Edu::Apps::ToolBox->apps_gate($WEB,$vars_ref);
return $WEB;
}
###################################################################
# SUBS
###################################################################
###################################################################
#### THAT'S IT :-D
###################################################################
1;
__END__