ONO::FW::Edu::Apps::Modules::MathRods

package ONO::FW::Edu::Apps::Modules::MathRods;
################################################################################
# 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::FW::Edu::Apps::ToolBox;
use ONO::FW::Edu::Apps::Modules::WorksheetMaker::Input;

use ONO::FW::Apps::ToolBox;

use ONO::Lib::UI::Radio;
use ONO::Lib::UI::Check;

use ONO::Lib::Data::Color;
use ONO::Lib::PDF::Draw;
use ONO::Lib::PDF::ToolBox;
use ONO::Lib::Image::Brick;

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 = "math_rods";

ONO::FW::Apps::Core->now("",$app,$vars{'app_lang'});

my @colors = ONO::Lib::Data::Color->rainbow("10");
my @colors_grey;

if ($vars{'app_input_print_options_blackwhite'}) {
for (my $i = 0; $i < 11; $i++) {
$colors[$i] = "grey:166:166:166";
}
}
for (my $i = 0; $i < 11; $i++) {
my $c = 220-$i*20;
$colors_grey[$i] = "grey:$c:$c:$c";
}

my $WEB;

$WEB .= ONO::FW::Apps::Core->output_paper_save($pdfkey,$BLK_ref,\%vars,$HTTP,$BASE,"$year$mon$mday");

my ($app_input_range_from,$app_input_range_to) = ONO::FW::Apps::Core->range_check(10,20,$vars{'app_input_range_from'},$vars{'app_input_range_to'});

$vars{'app_input_op_div'} = 0;
if (!$vars{'output_worksheet_maker'}) {
$vars{'app_input_op_mul'} = 0;
}

my @txt = (
"Count from",
"to",
"Multiply",
"Info page",
"print numbers",
);
if ($vars{'app_lang'} eq "de") {
@txt = (
"Zähle von",
"bis",
"Multiplikation",
"Info Seite",
"Zahlen drucken",
);
}
if ($vars{'app_lang'} eq "lu") {
@txt = (
"Ziel vun",
"bis",
"Multiplikatioun",
"Info Säit",
"Zuele printen",
);
}
if ($vars{'app_lang'} eq "fr") {
@txt = (
"Compte de",
"à",
"Multiplication",
"Page info",
"imprimer nombres",
);
}

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
#############################################################

if ($vars{'output_web'}) {

my $question_number = ONO::FW::Apps::Core->question_number($vars{'output_web_question_number'});

my ($op,$num1,$num2,$res);

$vars{'app_input_op_mul'} = 0;
$vars{'app_input_op_div'} = 0;

if ($vars{'app_input_type'} eq "count" || $vars{'app_input_type'} eq "multiply") {

if ($vars{'output_web_answer'} || $vars{'output_web_answer_op1'} || $vars{'output_web_answer_op2'}) {

my $mul_err;
if ($vars{'app_input_type'} eq "multiply") {
if ($vars{'output_web_answer_op1'} != $vars{'output_web_cache_op1'} || $vars{'output_web_answer_op2'} != $vars{'output_web_cache_op2'}) {
$mul_err++;
}
}

if ($vars{'output_web_answer'} != $vars{'output_web_cache_res'} || $mul_err) {

$vars{'output_web_answer_status'} = 2;
$vars{'output_web_mistakes'}++;

} else {

$question_number++;
$vars{'output_web_answer_status'} = 1;
$vars{'output_web_answer'} = "";
$vars{'output_web_answer_op1'} = "";
$vars{'output_web_answer_op2'} = "";
$vars{'output_web_cache_op1'} = "";
$vars{'output_web_cache_op2'} = "";
$vars{'output_web_cache_res'} = "";

}

}

} else {

if (!$vars{'output_web_answer'} || ($vars{'output_web_answer'} != $vars{'output_web_cache_res'})) {

$vars{'output_web_answer_status'} = 2;
$op = $vars{'output_web_cache_op'};
$num1 = $vars{'output_web_cache_num1'};
$num2 = $vars{'output_web_cache_num2'};
if ($vars{'output_web_answer'} && $vars{'output_web_answer'} != $vars{'output_web_cache_res'}) {
$vars{'output_web_mistakes'}++;
}

} else {

$question_number++;
$vars{'output_web_answer_status'} = 1;
$vars{'output_web_answer'} = "";

}

}

$WEB .= ONO::FW::Apps::Core->question_progress(
$vars{'app_input_number_of_questions'},
$question_number,
ONO::FW::Apps::Core->stats_replace(ONO::FW::Apps::Core->stats("",$BLK_ref,"cCWmtT"),$question_number-1,"","",$vars{'output_web_mistakes'},$vars{'output_web_completed'}),
"f",
);

if (ONO::FW::Apps::Core->question_progress_done($vars{'app_input_number_of_questions'},$question_number)) {

$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'});

if (!$op) {
$op = ONO::FW::Apps::Core->random_operation(ONO::FW::Apps::Core->get_operations(\%vars));
}
my $op_symbol = ONO::FW::Apps::Core->operation_symbol($op,"c");
my $INPUT = ONO::FW::Apps::Core->input_vars(\%vars);

if ($vars{'app_input_type'} eq "count") {

if ($vars{'output_web_cache_res'}) {
$res = $vars{'output_web_cache_res'};
} else {
$res = $vars{'app_input_count_from'}+int(rand($vars{'app_input_count_to'}-$vars{'app_input_count_from'}));
}

my ($RODS,$whilecounter);

my $display = $res;

while ($whilecounter < 255 && $display > 10) {
$whilecounter++;
$display = $display-10;
$RODS .= &rod("",10,\@colors,1);
}

if ($display) {
$RODS .= &rod("",$display,\@colors,1);
}

$WEB .= qq~<$form>
$INPUT
<input type="hidden" name="output_web_cache_res" value="$res">
<div class="w80 auto">
<div class="box_paper mt10" style="height:345px">
<table class="default_table auto">
<tr class="vtop">
<td><div class="mtx20">$RODS</div></td>
<td><div class="block32"></div></td>
<td>
~;

$WEB .= ONO::FW::Apps::Core->check_single(
"",
"",
50,
2,
$BLK_ref,
\%vars,
"nM",
);

$WEB .= qq~ </td>
</tr>
</table>
</div>
</div>
~;

}

if ($vars{'app_input_type'} eq "always") {

my ($ROD2,$RES3,$ALT1,$ALT2);

$res = $vars{'app_input_always_number'};
if (!$num1 || !$num2) {
($num1,$num2) = &always_nums("",$res,$vars{'output_web_cache_res'});
$vars{'output_web_cache_mode'} = "";
}

my @cols = split(/:/,$colors[$res-1]);
my $ROD1 = &rod("",$res,\@colors,1);
# if (ONO::IO->devstation) {
# $ROD1 = ONO::Lib::Image::Brick->brick($res,1,$colors[$res-1],"Bs");
# }
my $pad_right = 2;

if ($res > 10) {
@cols = split(/:/,$colors[$res-11]);
$ROD1 = &rod("",$res,\@colors,1);
$ROD2 = &rod("",($res-10),\@colors,1);
$pad_right = 0;
}

my @modes = (0,3);
my $use_res = $num2;

if ($vars{'output_web_cache_mode'} eq "3/0" || (!$vars{'output_web_cache_mode'} && int(rand(20)) > 9)) {
@modes = (3,0);
$use_res = $num1;
$ALT1 = qq~<td class="pad10_2 bold">$res</td><td class="pad10_2 bold">=</td>~;
$ALT2 = qq~<td class="pad10_2 bold">$op_symbol</td><td class="pad10_2 bold">$num2</td>~;
if ($op eq "sub") {
$ALT1 = qq~<td class="pad10_2 bold">$res</td><td class="pad10_2 bold">$op_symbol</td>~;
$ALT2 = qq~<td class="pad10_2 bold">=</td><td class="pad10_2 bold">$num2</td>~;
}
} else {
$ALT1 = qq~<td class="pad10_2 bold">$res</td><td class="pad10_2 bold">=</td><td class="pad10_2 bold">$num1</td><td class="pad10_2 bold">$op_symbol</td>~;
if ($op eq "sub") {
$ALT1 = qq~<td class="pad10_2 bold">$res</td><td class="pad10_2 bold">$op_symbol</td><td class="pad10_2 bold">$num1</td><td class="pad10_2 bold">=</td>~;
}
}

my $RES1 = &rod("",$num1,\@colors,$modes[0]);
my $RES2 = &rod("",$num2,\@colors,$modes[1]);
if ($num1 > 10 && $modes[0] == 0) {
$RES3 = $RES2;
$RES2 = &rod("",($num1-10),\@colors,1);
}
if ($num2 > 10 && $modes[1] == 0) {
$RES3 = $RES2;
$RES2 = &rod("",($num2-10),\@colors,0);
}

$WEB .= qq~<div class="inline auto">
<div class="rel" style="top:20px;padding-right:${pad_right}px">
<div class="center large col3 bold p5 bo" style="background-color:rgb($cols[1],$cols[2],$cols[3]);">
<div class="box_paper block20 radius20 auto center">$res</div>
</div>
</div>
<table class="default_table mt20">
<tr>
<td class="p0">$ROD1</td>
<td class="p0">$ROD2</td>
</tr>
</table>
<table class="default_table mt20">
<tr>
<td class="p0">$RES1</td>
<td class="p0">$RES2</td>
<td class="p0">$RES3</td>
</tr>
</table>
</div>
<$form>
$INPUT
<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="$use_res">
<input type="hidden" name="output_web_cache_mode" value="$modes[0]/$modes[1]">
~;

$WEB .= ONO::FW::Apps::Core->check_single(
$ALT1,
$ALT2,
50,
2,
$BLK_ref,
\%vars,
"n",
);


}

if ($vars{'app_input_type'} eq "calc") {

$WEB .= qq~<div style="padding-top:20px">
<div class="rel inline auto">
<table class="wide_table mb5">
<tr>
<td class="p5"></td>
<td class="w50 large center col9">10</td>
<td></td>
<td class="w50 large center col9">10</td>
<td class="p5"></td>
</tr>
<tr>
<td></td>
<td class="p5 bl bt br"></td>
<td></td>
<td class="p5 bl bt br"></td>
<td></td>
</tr>
</table>
<div class="rel inline auto">
<div class="box_fabric">
~;

$WEB .= &rod_row("",20);

my @resp = (32,20,10,5,332);
if (ONO::IO->device("phone")) {
@resp = (16,10,5,2,172);
} else {
$WEB .= qq~ <div class="abs bg_dark trans20" style="width:4px;height:56px;top:0px;left:170px"></div>
<div class="abs bg_dark" style="width:4px;height:56px;top:0px;left:330px"></div>
<div class="abs bg_dark trans20" style="width:4px;height:56px;top:0px;left:491px"></div>
~;
}

if ($op eq "add") {

if (!$num1 || !$num2) {

$num1 = ONO::FW::Apps::Core->random_number(1,$app_input_range_to,1,10,\%vars);
$num2 = ONO::FW::Apps::Core->random_number(1,$app_input_range_to,1,10,\%vars);

}

$res = $num1 + $num2;

$WEB .= qq~<div class="abs inline" style="top:11px;left:11px">~;
$WEB .= &rod("",$num1,\@colors);
$WEB .= qq~</div>~;

my $left = 11+($num1*$resp[0]);

$WEB .= qq~<div class="abs inline" style="top:11px;left:${left}px">~;
$WEB .= &rod("",$num2,\@colors);
$WEB .= qq~</div>~;

}

if ($op eq "sub") {

if (!$num1 || !$num2) {

$num1 = ONO::FW::Apps::Core->random_number($app_input_range_from,$app_input_range_to,2,"",$vars_ref);
$num2 = ONO::FW::Apps::Core->random_number(1,$num1,1,10,$vars_ref);

}

$res = $num1 - $num2;

$WEB .= qq~<div class="abs inline" style="top:11px;left:11px">~;
$WEB .= &rod("",$num1,\@colors,2);
$WEB .= qq~</div>~;

if ($num1 > 10) {
$WEB .= qq~<div class="abs inline" style="top:11px;left:$resp[4]px">~;
$WEB .= &rod("",$num1-10,\@colors,2);
$WEB .= qq~</div>~;
}

$WEB .= qq~<div class="rel" style="padding-top:50px">~;
$WEB .= &rod_row("",20);
if (!ONO::IO->device("phone")) {
$WEB .= qq~ <div class="abs bg_dark trans20" style="width:4px;height:56px;top:38px;left:159px"></div>
<div class="abs bg_dark" style="width:4px;height:56px;top:38px;left:319px"></div>
<div class="abs bg_dark trans20" style="width:4px;height:56px;top:38px;left:480px"></div>
~;
}

if ($num1 > 9 && $num2 != 10) {

# res is left

$WEB .= qq~ <div class="abs inline" style="top:50px;left:0px">~;
$WEB .= &rod("",$res,\@colors,3);
$WEB .= qq~ </div>~;

my $left = $res * $resp[0];
$WEB .= qq~ <div class="abs inline" style="top:50px;left:${left}px">~;
$WEB .= &rod("",$num2,\@colors);
$WEB .= qq~ </div>~;

if ($num2 > 10) {
my $left = $res * $resp[0] + $resp[0] * 10;
$WEB .= qq~ <div class="abs inline" style="top:50px;left:${left}px">~;
$WEB .= &rod("",$num2-10,\@colors);
$WEB .= qq~ </div>~;
}

} else {

# res is right

$WEB .= qq~ <div class="abs inline" style="top:50px;left:0px">~;
$WEB .= &rod("",$num2,\@colors);
$WEB .= qq~ </div>~;

if ($num2 > 10) {
my $left = 10 * $resp[0];
$WEB .= qq~ <div class="abs inline" style="top:50px;left:${left}px">~;
$WEB .= &rod("",$num2-10,\@colors);
$WEB .= qq~ </div>~;
}

my $left = $num2 * $resp[0];
$WEB .= qq~ <div class="abs inline" style="top:50px;left:${left}px">~;
$WEB .= &rod("",$res,\@colors,3);
$WEB .= qq~ </div>~;

}

$WEB .= qq~</div>~;

}

$WEB .= qq~ </div>
</div>
</div>
</div>
<$form>
$INPUT
<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">
~;

$WEB .= ONO::FW::Apps::Core->check_single(
qq~<td class="pad10_2 bold">$num1</td>
<td class="pad10_2 bold">$op_symbol</td>
<td class="pad10_2 bold">$num2</td>
<td class="pad10_2 bold">=</td>
~,
"",
50,
2,
$BLK_ref,
\%vars,
"n",
);

}

if ($vars{'app_input_type'} eq "multiply") {

my ($op1,$op2);

if ($vars{'output_web_cache_res'}) {

$op1 = $vars{'output_web_cache_op1'};
$op2 = $vars{'output_web_cache_op2'};
$res = $vars{'output_web_cache_res'};

} else {

my (
$ops1_ref,$ops2_ref,
$ops1_num,$ops2_num,
) = &mul_ops("",\%vars);
my @ops1 = @$ops1_ref;
my @ops2 = @$ops2_ref;

$op1 = $ops1[int(rand($ops1_num))];
$op2 = $ops2[int(rand($ops2_num))];

$res = $op1*$op2;
}

my $NUM1 = qq~<td><input type="text" id="output_web_answer_op1_id" name="output_web_answer_op1" value="$vars{'output_web_answer_op1'}" autocomplete="off" class="center" style="width:25px" maxlength="2" placeholder="?"></td>
<td>•</td>
<td><input type="text" id="output_web_answer_op2_id" name="output_web_answer_op2" value="$vars{'output_web_answer_op2'}" autocomplete="off" class="center" style="width:25px" maxlength="2" placeholder="?"></td>
<td>=</td>
~;

my $RODS;
for (my $r = 0; $r < $op1; $r++) {
$RODS .= &rod("",$op2,\@colors,1);
}

$WEB .= qq~<$form>
$INPUT
<input type="hidden" name="output_web_cache_res" value="$res">
<input type="hidden" name="output_web_cache_op1" value="$op1">
<input type="hidden" name="output_web_cache_op2" value="$op2">
<div class="w90 auto">
<div class="box_paper mt10" style="height:345px">
<table class="default_table auto">
<tr class="vtop">
<td><div class="mtx20">$RODS</div></td>
<td><div class="block32"></div></td>
<td>
~;

$WEB .= ONO::FW::Apps::Core->check_single(
$NUM1,
"",
50,
2,
$BLK_ref,
\%vars,
"FM",
);

$WEB .= qq~ </td>
</tr>
</table>
</div>
</div>
<script>onojs_focus('output_web_answer_op1_id');</script>
~;

}

$WEB .= qq~</form>~;

}

}

#############################################################
# PDF
#############################################################

if ($vars{'output_paper'}) {

$WEB .= ONO::FW::Apps::Core->output_paper($pdfkey,\%BLK,\%vars,$HTTP,$BASE);

my $OPTS;
my $cols = 2;
if ($vars{'app_input_type'} eq "calc") {
if ($app_input_range_to < 16) {
$cols = 3;
}
if ($app_input_range_to < 11) {
$cols = 4;
}
}
if ($vars{'app_input_type'} eq "always") {
if ($vars{'app_input_always_number'} < 13) {
$cols = 3;
}
if ($vars{'app_input_always_number'} < 9) {
$cols = 4;
}
} else {
$OPTS = ONO::FW::Apps::Core->headers_options($BLK_ref,$vars_ref);
}

ONO::FW::Apps::PDF->new("$BASE/pdf/pdf-$pdfkey.pdf","",$format);

foreach my $copy (ONO::FW::Apps::Core->unique_copies($vars{'app_input_print_options_unique_copies'})) {

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'},$OPTS,$vars{'app_input_print_options_code'},$format);
ONO::FW::Apps::Core->unique_copies_info($canvas,$copy,$vars_ref);

# ONO::Lib::PDF::ToolBox->canvas_test($canvas);

my (@corr_cache,$counter,@last,%used);

my $max_y = 8;

if ($vars{'app_input_type'} eq "info") {

$max_y = 0;

ONO::Lib::PDF::Draw->font("HB",28);

for (my $b = 0; $b < $vars{'app_input_info_to'}; $b++) {
ONO::Lib::PDF::Draw->rect($canvas,5, $b*19+1, 25, $b*19+15, 1,"0:25:25:25","0:240:240:240",1);
ONO::Lib::PDF::Draw->brick($canvas,30, $b*19+1, $b+1, 1,14,0.5,$colors[$b]);
if ($vars{"app_input_info_nums"}) {
ONO::Lib::PDF::Draw->text($canvas,15,$b*19+11.5,$b+1,"c");
}
}

ONO::Lib::PDF::Draw->font("H",12);

} else {

ONO::FW::Apps::Core::Graphics->pdf_draw_item_numbers($canvas,-2,0,1,4,"HV",$vars_ref);

}

if ($vars{'app_input_type'} eq "count" && $vars{'app_input_count_to'} < 11) {
$cols = 4;
}

for (my $y = 0; $y < $max_y; $y++) {
for (my $x = 0; $x < $cols; $x++) {

$counter++;

my $op = ONO::FW::Apps::Core->random_operation(ONO::FW::Apps::Core->get_operations($vars_ref));
my $op_symbol = ONO::FW::Apps::Core->operation_symbol($op,"p");
my ($num1,$num2,$res);

if ($vars{'app_input_type'} eq "count") {

$cols = 3;

if ($vars{'app_input_type'} eq "count" && $vars{'app_input_count_to'} < 11) {
$cols = 4;
}

my $whilecounter;
while ($whilecounter < 256 && (!$res || $used{$res})) {
$whilecounter++;
$res = 1+$vars{'app_input_count_from'}+int(rand($vars{'app_input_count_to'}-$vars{'app_input_count_from'}));
}

if ($y%2 == 0 || $vars{"last_rows_$x"} < 5) {

my ($offset_x,$offset_y) = &pdf_always_pos("",$x,$y,$cols,$res,\@colors,$canvas,1);

if ($y%2 != 0) {
$offset_y = ($y*23.75) + ($vars{"last_rows_$x"}*3.5) - 7;
my $remaining_rows = 5 - $vars{"last_rows_$x"};
my $remaining_res = $remaining_rows * 10;
if ($vars{'app_input_count_to'} < $remaining_res) {
$remaining_res = $vars{'app_input_count_to'};
}
$res = 0;
my $whilecounter;
while ($whilecounter < 256 && (!$res || $used{$res})) {
$whilecounter++;
$res = $vars{'app_input_count_from'}+int(rand($remaining_res-$vars{'app_input_count_from'}));
if ($res > $remaining_res || $res < 1) {
$res = 1+int(rand($remaining_res));
}
}
}

my ($rows,$off_y) = &pdf_count_block("",$canvas,$offset_x,$offset_y,$res,@colors);

$vars{"last_rows_$x"} = $rows;

$used{$res}++;

$corr_cache[$counter] = "$res:$offset_x,$offset_y";

my $add_y;
if ($rows < 10) {
$add_y = 1.5;
}

ONO::Lib::PDF::Draw->rect($canvas,$offset_x,$offset_y+$off_y+5,$offset_x+12,$offset_y+$off_y+10+$add_y,1,"0:25:25:25","0:240:240:240",1);

}

}

if ($vars{'app_input_type'} eq "always") {

$res = $vars{'app_input_always_number'};

my ($offset_x,$offset_y) = &pdf_always_pos("",$x,$y,$cols,$res,\@colors,$canvas);

my $x_id = ($x+1)*10;

# $last[1] and $last[2] check horizontally, while x_ids check vertically

($num1,$num2) = &always_nums("",$res,0,$last[1],$last[2],$last[$x_id+1],$last[$x_id+2]);
($last[1],$last[2]) = ($num1,$num2);
($last[$x_id+1],$last[$x_id+2]) = ($num1,$num2);
my $mode = 0;
if (int(rand(20)) > 9) {
$mode = 1;
}

my ($print_num1,$print_num2) = ($num1,$num2);
my ($symbol1,$symbol2) = ("=",$op_symbol);
if ($op eq "sub") {
($symbol1,$symbol2) = ($op_symbol,"=");
}

&pdf_always("",$canvas,$offset_x,$offset_y,$res,$num1,$num2,$mode,$print_num1,$print_num2,$symbol1,$symbol2,\@colors,$cols);

$corr_cache[$counter] = "$res:$num1:$num2:$symbol1:$symbol2";

}

if ($vars{'app_input_type'} eq "calc") {

my ($offset_x,$offset_y) = &pdf_base_rod("",$x,$y,$canvas,$op,$cols);

if ($op eq "add") {
my $whilecounter;
while ($whilecounter < 256 && (!$whilecounter || $res < $app_input_range_from || $res > $app_input_range_to || $used{"$op,$num1,$num2"})) {
$whilecounter++;
$num1 = ONO::FW::Apps::Core->random_number(1,$app_input_range_to,1,10,$vars_ref);
$num2 = ONO::FW::Apps::Core->random_number(1,$app_input_range_to,1,10,$vars_ref);
$res = $num1 + $num2;
}
}

if ($op eq "sub") {

my $whilecounter;
while ($whilecounter < 256 && (!$whilecounter || $res < $app_input_range_from || $res > $app_input_range_to || $used{"$op,$num1,$num2"})) {
$whilecounter++;
$num1 = ONO::FW::Apps::Core->random_number($app_input_range_from,$app_input_range_to,2,"",$vars_ref);
$num2 = ONO::FW::Apps::Core->random_number(1,$num1,1,10,$vars_ref);
$res = $num1 - $num2;
}
}

$used{"$op,$num1,$num2"}++;

&pdf_rod_and_text("",$canvas,$offset_x,$offset_y,$op,$op_symbol,$num1,$num2,$res,\@colors,0);

$corr_cache[$counter] = "$op:$op_symbol:$num1:$num2:$res";

}

if ($vars{'app_input_type'} eq "multiply") {

$cols = 3;

if ($y%2 == 0 || $vars{"last_rows_$x"} < 5) {

my ($offset_x,$offset_y) = &pdf_always_pos("",$x,$y,$cols,$res,\@colors,$canvas,1);

my (
$ops1_ref,$ops2_ref,
$ops1_num,$ops2_num,
) = &mul_ops("",\%vars);
my @ops1 = @$ops1_ref;
my @ops2 = @$ops2_ref;

my ($op1,$op2);

if ($y%2 == 0) {

my $whilecounter;
while ($whilecounter < 255 && (!$op1 || !$op2 || $used{"$op1,$op2"})) {
$whilecounter++;
$op1 = $ops1[int(rand($ops1_num))];
$op2 = $ops2[int(rand($ops2_num))];
}

$used{"$op1,$op2"}++;

for (my $b = 0; $b < $op1; $b++) {
ONO::Lib::PDF::Draw->brick($canvas,$offset_x,$offset_y+$b*3.5,$op2,1,3.5,0.5,$colors[$op2-1]);
}

} else {

$offset_y = ($y*23.75) + ($vars{"last_rows_$x"}*3.5) - 7;

my $whilecounter;
while ($whilecounter < 255 && (!$op1 || $op1 > 5-$vars{"last_rows_$x"})) {
$whilecounter++;
$op1 = $ops1[int(rand($ops1_num))];
}

if ($op1) {

my $whilecounter;
while ($whilecounter < 255 && (!$op2 || $used{"$op1,$op2"})) {
$whilecounter++;
$op2 = $ops2[int(rand($ops2_num))];
}

for (my $b = 0; $b < $op1; $b++) {
ONO::Lib::PDF::Draw->brick($canvas,$offset_x,$offset_y+$b*3.5,$op2,1,3.5,0.5,$colors[$op2-1]);
}

}
}

if ($op1) {

$corr_cache[$counter] = "$op1:$op2:$offset_x:$offset_y";

$vars{"last_rows_$x"} = $op1;

&pdf_mul_info("",$canvas,$offset_x,$offset_y,$op1,$op2);

}

}

}

}
}

if (ONO::FW::Apps::Core->print_corrections("$BASE/pdf/pdf-$pdfkey-corr.pdf","",$format,$vars_ref) && $vars{'app_input_type'} ne "info") {

ONO::FW::Apps::Core->headers(\%vars,$format,"c");
ONO::FW::Apps::PDF->title($BLK{'Corrections'},$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);

$counter = 0;

for (my $y = 0; $y < 8; $y++) {
for (my $x = 0; $x < $cols; $x++) {

$counter++;

if ($vars{'app_input_type'} eq "count") {

my ($res,$offset_x,$offset_y) = split(/:/,$corr_cache[$counter]);

if ($res) {

$offset_y = $offset_y + $y * 23.75;

my ($rows,$off_y) = &pdf_count_block("",$canvas,$offset_x,$offset_y,$res,@colors_grey);

ONO::Lib::PDF::Draw->rect($canvas,$offset_x,$offset_y+$off_y+5,$offset_x+12,$offset_y+$off_y+10,1,"0:25:25:25","0:240:240:240",1);
ONO::Lib::PDF::Draw->text($canvas,$offset_x+6,$offset_y+$off_y+9,$res,"c");

}

}

if ($vars{'app_input_type'} eq "always") {

my ($res,$num1,$num2,$symbol1,$symbol2) = split(/:/,$corr_cache[$counter]);

my ($offset_x,$offset_y) = &pdf_always_pos("",$x,$y,$cols,$res,\@colors_grey,$canvas);

&pdf_always("",$canvas,$offset_x,$offset_y,$res,$num1,$num2,0,$num1,$num2,$symbol1,$symbol2,\@colors_grey,$cols,1);

}

if ($vars{'app_input_type'} eq "calc") {

my ($op,$op_symbol,$num1,$num2,$res) = split(/:/,$corr_cache[$counter]);

my ($offset_x,$offset_y) = &pdf_base_rod("",$x,$y,$canvas,"",$cols);

&pdf_rod_and_text("",$canvas,$offset_x,$offset_y,$op,$op_symbol,$num1,$num2,$res,\@colors_grey,1);

}

if ($vars{'app_input_type'} eq "multiply") {

my ($op1,$op2,$offset_x,$offset_y) = split(/:/,$corr_cache[$counter]);

if ($op1 && $op2) {

for (my $b = 0; $b < $op1; $b++) {
ONO::Lib::PDF::Draw->brick($canvas,$offset_x,$offset_y+$b*3.5,$op2,1,3.5,0.5,$colors_grey[$op2-1]);
}

&pdf_mul_info("",$canvas,$offset_x,$offset_y,$op1,$op2,$op1*$op2);

}

}

}
}
}

}

ONO::FW::Apps::PDF->end;

}

if ($vars{'output_web'}) {
ONO::FW::Apps::Core->varstore($vars{'username'},$vars{'virclass'},$vars{'anonymous'},\%vars);
}

} else {

#############################################################
# EXERCISE SETUP
#############################################################

$WEB .= qq~<div class="abs hide600" style="top:90px;right:10px">~;
for (my $i = 1; $i < 11; $i++) {
my $ROD = &rod("",$i,\@colors,1);

# if (ONO::IO->devstation) {
# $ROD = ONO::Lib::Image::Brick->brick($i,1,$colors[$i-1],"Bs");
# }

$WEB .= qq~<div class="inline w100">
<table class="default_table fr"><tr><td class="pad10_2 tar large">$i</td><td>$ROD</td></tr></table>
</div>
~;
}
$WEB .= qq~</div>~;

my @opts = (
"count;rods_sel_0();",
"always;rods_sel_1();",
"calc;rods_sel_2();",
"multiply;rods_sel_3();",
"info;rods_sel_4();"
);

my $sel = "count";
if ($vars{'app_input_type'} =~ /(info|count|always|calc|multiply)/) {
$sel = $vars{'app_input_type'}
}

if ($vars{'app_input_count_from'} > $vars{'app_input_count_to'}) {
$vars{'app_input_count_from'} = 1;
}

my @RADIO = ONO::Lib::UI::Radio->buttons("app_input_type",\@opts,$sel,"r");

my ($SEL,$SEL0,$SEL1,$sel_used,$sel_used0,$sel_used1);
foreach my $opt (1,5,10,15,20,30,40,50,60,70,80,90,100) {
my ($sel,$sel0,$sel1);
if ($vars{'app_input_always_number'} == $opt || (!$vars{'app_input_always_number'} && $opt == 10)) {
$sel_used++;
$sel = " selected";
}
if ($vars{'app_input_count_from'} == $opt || (!$vars{'app_input_count_from'} && $opt == 1)) {
$sel_used0++;
$sel0 = " selected";
}
if ($vars{'app_input_count_to'} == $opt || (!$vars{'app_input_count_to'} && $opt == 100)) {
$sel_used1++;
$sel1 = " selected";
}
$SEL0 .= qq~<option value="$opt"$sel0>$opt</option>~;
$SEL1 .= qq~<option value="$opt"$sel1>$opt</option>~;
if ($opt < 21) {
$SEL .= qq~<option value="$opt"$sel>$opt</option>~;
}
}
$SEL .= qq~<option value="10">----</option>~;
$SEL0 .= qq~<option value="0">----</option>~;
$SEL1 .= qq~<option value="10">----</option>~;
for (my $i = 5; $i < 101; $i++) {
my ($sel,$sel0,$sel1);
if (!$sel_used && $vars{'app_input_always_number'} == $i) {
$sel = " selected";
}
if (!$sel_used0 && $vars{'app_input_count_from'} == $i) {
$sel0 = " selected";
}
if (!$sel_used1 && $vars{'app_input_count_to'} == $i) {
$sel1 = " selected";
}
if ($i < 21) {
$SEL .= qq~<option value="$i"$sel>$i</option>~;
}
$SEL0 .= qq~<option value="$i"$sel0>$i</option>~;
$SEL1 .= qq~<option value="$i"$sel1>$i</option>~;
}

my $COUNT = qq~<table class="default_table">
<tr>
<td class="cursorlink" onclick="rods_sel_0();">$txt[0]</td>
<td></td>
<td class="p0">
<div id="app_input_count_id">
<table class="default_table">
<tr>
<td class="p0">
<div class="select"><select name="app_input_count_from">
$SEL0
</select></div>
</td>
<td></td>
<td class="cursorlink" onclick="rods_sel_0();">$txt[1]</td>
<td></td>
<td class="p0">
<div class="select"><select name="app_input_count_to">
$SEL1
</select></div>
</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
~;

my $ALWAYS = qq~<table class="default_table">
<tr>
<td class="cursorlink" onclick="rods_sel_1();">$BLK{'Always'}...</td>
<td></td>
<td class="p0">
<div id="app_input_always_number_id">
<div class="select"><select name="app_input_always_number">
$SEL
</select></div>
</div>
</td>
</tr>
</table>
~;
my $CALCULATE = qq~<div class="cursorlink" onclick="rods_sel_2();">
$BLK{'Calculate'}:
</div>
~;

my ($SEL,$SW1,$SW2,$mul_found,$SEL2);

foreach my $opt ("2:2","5:5","1_10:----","2_5:2, 5","2_5_10:2, 5, 10","1_10:----","1_5:1 - 5","1_10:1 - 10","1_10:----") {
my @op = split(/:/,$opt);
my $sel;
if ($op[1] !~ /----/ && ($vars{'app_input_multiply_mul'} eq $op[0] || (!$vars{'app_input_multiply_mul'} && $op[0] eq "1_10"))) {
$sel = " selected";
}
$SEL .= qq~<option value="$op[0]"$sel>$op[1]</option>~;
}

for (my $i = 1; $i < 11; $i++) {
if ($vars{"app_input_mulrow_$i"}) {
$mul_found++;
}
$SEL .= qq~<option value="$i">$i</option>~;
my $sel;
if ($vars{'app_input_info_to'} == $i || (!$vars{'app_input_info_to'} && $i == 10)) {
$sel = " selected";
}
$SEL2 .= qq~<option value="$i"$sel>$i</option>~;
}

for (my $i = 1; $i < 11; $i++) {
if (!$mul_found && $i < 6) {
$vars{"app_input_mulrow_$i"}++;
}
my $SW = ONO::Lib::UI::Check->switch("app_input_mulrow_$i",$vars{"app_input_mulrow_$i"},"mv");
$SW1 .= qq~<td>$SW</td>~;
$SW2 .= qq~<td class="center">$i</td>~;
}

my $MULTIPLY = qq~<div onclick="rods_sel_3();">$txt[2]:</div>
<div id="app_input_multiply_id">
<table class="default_table">
<tr>
<td><div class="select"><select name="app_input_multiply_mul">$SEL</select></div></td>
<td>•</td>
$SW1
<td>= .....</td>
</tr>
<tr>
<td></td>
<td></td>
$SW2
<td></td>
</tr>
</table>
</div>
~;

my $SW = ONO::Lib::UI::Check->switch("app_input_info_nums",$vars{"app_input_info_nums"},"mv");

my $INFO = qq~<table class="default_table">
<tr>
<td class="cursorlink" onclick="rods_sel_4();">$txt[3]</td>
<td></td>
<td class="p0">
<div id="app_input_info_id">
<table class="default_table">
<tr>
<td class="p0">1</td>
<td>-</td>
<td class="p0">
<div class="select"><select name="app_input_info_to">
$SEL2
</select></div>
</td>
<td class="p5"></td>
<td>$SW</td>
<td>$txt[4]</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
~;

my $CONF;

$CONF .= ONO::FW::Apps::ToolBox->conf_input("custom", $BLK_ref,\%vars,"",$RADIO[1],$COUNT);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("custom", $BLK_ref,\%vars,"",$RADIO[2],$ALWAYS);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("spacer", $BLK_ref,\%vars,"","s");
$CONF .= ONO::FW::Apps::ToolBox->conf_input("custom", $BLK_ref,\%vars,"",$RADIO[3],$CALCULATE);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("range", $BLK_ref,\%vars,"ItN",1,20,20);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("spacer", $BLK_ref,\%vars);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("ops", $BLK_ref,\%vars,"","as-AS");
$CONF .= ONO::FW::Apps::ToolBox->conf_input("spacer", $BLK_ref,\%vars);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("custom", $BLK_ref,\%vars,"T",$RADIO[4],$MULTIPLY);

if (!$vars{'output_web'}) {
$CONF .= ONO::FW::Apps::ToolBox->conf_input("custom", $BLK_ref,\%vars,"",$RADIO[5],$INFO);
}

$CONF .= $RADIO[0];

$WEB .= ONO::FW::Apps::Core->conf_box(
$db,
$community,
$app,
$form,
"",
$action_url,
$CONF,
$lang,
$BLK_ref,
\%vars,
"op-ncbdi-CDI-lsu-N",
);

$WEB .= qq~<script>
function rods_sel_0() {
onojs_class('ono_fwapps_input_row_range','trans50');onojs_class('app_input_always_number_id','trans50');onojs_class('app_input_count_id','');
onojs_class('app_input_multiply_id','trans50');onojs_class('app_input_info_id','trans50');
onojs_ui_radio_app_input_type_select('count','button_green','bg_paper');
}
function rods_sel_1() {
onojs_class('ono_fwapps_input_row_range','trans50');onojs_class('app_input_always_number_id','');onojs_class('app_input_count_id','trans50');
onojs_class('app_input_multiply_id','trans50');onojs_class('app_input_info_id','trans50');
onojs_ui_radio_app_input_type_select('always','button_green','bg_paper');
}
function rods_sel_2() {
onojs_class('ono_fwapps_input_row_range','');onojs_class('app_input_always_number_id','trans50');onojs_class('app_input_count_id','trans50');
onojs_class('app_input_multiply_id','trans50');onojs_class('app_input_info_id','trans50');
onojs_ui_radio_app_input_type_select('calc','button_green','bg_paper');
}
function rods_sel_3() {
onojs_class('ono_fwapps_input_row_range','trans50');onojs_class('app_input_always_number_id','trans50');onojs_class('app_input_count_id','trans50');
onojs_class('app_input_multiply_id','');onojs_class('app_input_info_id','trans50');
onojs_ui_radio_app_input_type_select('multiply','button_green','bg_paper');
}
function rods_sel_4() {
onojs_class('ono_fwapps_input_row_range','trans50');onojs_class('app_input_always_number_id','trans50');onojs_class('app_input_count_id','trans50');
onojs_class('app_input_multiply_id','trans50');onojs_class('app_input_info_id','');
onojs_ui_radio_app_input_type_select('info','button_green','bg_paper');
}
</script>
~;

if ($vars{'app_input_type'} eq "count") {
$WEB .= qq~<script>rods_sel_0();</script>~;
}
if ($vars{'app_input_type'} eq "always") {
$WEB .= qq~<script>rods_sel_1();</script>~;
}
if ($vars{'app_input_type'} eq "calc") {
$WEB .= qq~<script>rods_sel_2();</script>~;
}
if ($vars{'app_input_type'} eq "multiply") {
$WEB .= qq~<script>rods_sel_3();</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
###################################################################

sub always_nums {

my $num1 = 1+int(rand($_[1]-1));
my $num2 = $_[1] - $num1;

# rescramble a few times if identical...

my $whilecounter;
while ($whilecounter < 8 && ($num1 == $_[2] || $num2 == $_[2] || $num1 == $_[3] || $num2 == $_[4] || $num1 == $_[5] || $num2 == $_[6])) {
$whilecounter++;
$num1 = 1+int(rand($_[1]-1));
$num2 = $_[1] - $num1;
}

return ($num1,$num2);

}

sub rod {

my (
$self,
$size,
$colors_ref,
$mode,
) = @_;

# modes (3):
#
# 0 default,
# 1 no length info below the rod
# 2 length info closer to rod
# 3 question mark instead of length info, no color, no 10-limit
# 4 length info on top of

my @colors = @$colors_ref;

my @resp = (32,20,10,5);
if (ONO::IO->device("phone")) {
@resp = (16,10,5,2);
}

if ($mode != 3 && $size > 10) {
$size = 10;
}
my $width = $size*$resp[0];
my @cp = split(/:/,$colors[$size-1]);
my $BULLET = "box_fabric p0 block$resp[1] radius$resp[2] auto trans70";

if ($mode == 3) {
@cp = (0,244,244,244);
$BULLET = "";
}

my $ROD;

if (!ONO::IO->device("phone")) {

if ($mode == 4) {
$ROD .= qq~ <div class="center large col3 bold">$size</div><div class="p5 bl bt br mb5"></div>~;
}

}

$ROD .= qq~<div class="rel block$resp[0] bo" style="width:${width}px">
<div style="background-color:rgb($cp[1],$cp[2],$cp[3]);">
<table class="default_table">
<tr>
~;
for (my $i = 0; $i < $size; $i++) {
$ROD .= qq~ <td class="p0">
<div class="block$resp[0]">
<div class="rel" style="top:$resp[3]px">
<div class="$BULLET"></div>
</div>
</div>
</td>
~;
}

$ROD .= qq~ </tr>
</table>
</div>
~;

if (!ONO::IO->device("phone")) {

if ($mode == 0) {
$ROD .= qq~ <div class="p5 bl bb br mt20"></div><div class="center large col3 bold">$size</div>~;
}
if ($mode == 2) {
$ROD .= qq~ <div class="p5 bl bb br mt5"></div><div class="center large col3 bold">$size</div>~;
}
if ($mode == 3) {
$ROD .= qq~ <div class="abs lightred large bold center" style="top:5px;width:${width}px">?</div>~;
}

}

$ROD .= qq~</div>~;

return $ROD;

}

sub rod_row {

my $ROW = qq~ <div class="inline bg_paper bo">
<table class="default_table">
<tr>
~;

my @resp = (32,20,10,5);
if (ONO::IO->device("phone")) {
@resp = (16,10,5,2);
}

for (my $i = 0; $i < $_[1]; $i++) {
my $CLASS;
if ($i == 10) {
$CLASS = " bl";
}
$ROW .= qq~ <td class="p0$CLASS">
<div class="block$resp[0]">
<div class="rel" style="top:$resp[3]px">
<div class="box_fabric p0 block$resp[1] radius$resp[2] auto"></div>
</div>
</div>
</td>
~;
}

$ROW .= qq~ <tr>
</table>
</div>
~;

return $ROW;

}

sub pdf_count_block {

my (
$self,
$canvas,
$offset_x,
$offset_y,
$res,
@colors,
) = @_;

my ($whilecounter,$rows,$off_y);

while ($whilecounter < 255 && $res > 10) {
$whilecounter++;
$res = $res-10;
ONO::Lib::PDF::Draw->brick($canvas,$offset_x,$offset_y+$off_y,10,1,3.5,0.5,$colors[9]);
$off_y = $off_y+3.5;
$rows++;
}

if ($res) {
ONO::Lib::PDF::Draw->brick($canvas,$offset_x,$offset_y+$off_y,$res,1,3.5,0.5,$colors[$res-1]);
$rows++;
}

return ($rows,$off_y);

}

sub pdf_always_pos {

my $colors_ref = $_[5];
my @colors = @$colors_ref;

my $offset_x = 5 + ($_[1] * 100);
my $offset_y = ($_[2] * 23.75)+3;

if ($_[3] == 3) {
$offset_x = 5 + ($_[1] * 62);
}
if ($_[3] == 4) {
$offset_x = 5 + ($_[1] * 43);
}

if (!$_[6]) {

if ($_[4] < 11) {
ONO::Lib::PDF::Draw->brick($_[6],$offset_x,$offset_y,$_[4],1,3.5,0.5,$colors[$_[4]-1]);
} else {
ONO::Lib::PDF::Draw->brick($_[6],$offset_x,$offset_y,10,1,3.5,0.5,$colors[9]);
ONO::Lib::PDF::Draw->brick($_[6],$offset_x+35,$offset_y,$_[4]-10,1,3.5,0.5,$colors[$_[4]-11]);
}

}

return ($offset_x,$offset_y);

}

sub pdf_base_rod {

my $mul_x = 95;
my $brick = 20;
my $sep = 4;
if ($_[5] == 3) {
$mul_x = 56;
$brick = 15;
$sep = 3;
}
if ($_[5] == 4) {
$mul_x = 43;
$brick = 10;
$sep = 2;
}

my $offset_x = 5 + ($_[1] * $mul_x);

my $offset_y = ($_[2] * 23.75)+3;

my $offset_sub = 0;

if ($_[4] eq "add") {
$offset_y = $offset_y + 3.5;
} else {
$offset_sub = 3.5;
}

ONO::Lib::PDF::Draw->brick($_[3],$offset_x,$offset_y,$brick,1,3.5,0.1);
for (my $i = 1; $i < $sep; $i++) {
ONO::Lib::PDF::Draw->line($_[3],$offset_x+$i*5*3.5,$offset_y-1,$offset_x+$i*5*3.5,$offset_y+4.5+$offset_sub,0.1);
}

return ($offset_x,$offset_y);

}

sub pdf_rod_and_text {

my (
$self,
$canvas,
$offset_x,
$offset_y,
$op,
$op_symbol,
$num1,
$num2,
$res,
$colors_ref,
$mode,
) = @_;

my @colors = @$colors_ref;

if ($op eq "add") {

ONO::Lib::PDF::Draw->brick($canvas,$offset_x,$offset_y,$num1,1,3.5,0.5,$colors[$num1-1]);
ONO::Lib::PDF::Draw->brick($canvas,$offset_x+($num1*3.5),$offset_y,$num2,1,3.5,0.5,$colors[$num2-1]);

$offset_y = $offset_y - 3.5;

}

if ($op eq "sub") {

ONO::Lib::PDF::Draw->brick($canvas,$offset_x,$offset_y+3.5,20,1,3.5,0.1);
for (my $i = 1; $i < 4; $i++) {
ONO::Lib::PDF::Draw->line($canvas,$offset_x+$i*5*3.5,$offset_y-1,$offset_x+$i*5*3.5,$offset_y+7,0.1);
}

my $brick1 = $num1;
if ($brick1 > 10) {
$brick1 = 10;
my $brick2 = $num1 - $brick1;
ONO::Lib::PDF::Draw->brick($canvas,$offset_x+35,$offset_y,$brick2,1,3.5,0.5,$colors[$brick2-1]);
}
ONO::Lib::PDF::Draw->brick($canvas,$offset_x,$offset_y,$brick1,1,3.5,0.5,$colors[$brick1-1]);

if ($num1 > 9 && $num2 != 10) {

# res is left
my $brick1 = $num2;
if ($brick1 > 10) {
$brick1 = 10;
my $brick2 = $num2 - $brick1;
ONO::Lib::PDF::Draw->brick($canvas,$offset_x+35+$res*3.5,$offset_y+3.5,$brick2,1,3.5,0.5,$colors[$brick2-1]);
}
ONO::Lib::PDF::Draw->brick($canvas,$offset_x+$res*3.5,$offset_y+3.5,$brick1,1,3.5,0.5,$colors[$brick1-1]);
ONO::Lib::PDF::Draw->rect($canvas,$offset_x,$offset_y+3.5,$offset_x+$res*3.5,$offset_y+7,1,"","white:222:222:222");

} else {

# res is right

my $brick1 = $num2;
if ($brick1 > 10) {
$brick1 = 10;
my $brick2 = $num2 - $brick1;
ONO::Lib::PDF::Draw->brick($canvas,$offset_x+35,$offset_y+3.5,$brick2,1,3.5,0.5,$colors[$brick2-1]);
}
ONO::Lib::PDF::Draw->brick($canvas,$offset_x,$offset_y+3.5,$brick1,1,3.5,0.5,$colors[$brick1-1]);
ONO::Lib::PDF::Draw->rect($canvas,$offset_x+$num2*3.5,$offset_y+3.5,$offset_x+$num2*3.5+$res*3.5,$offset_y+7,1,"","white:222:222:222");

}

}

ONO::Lib::PDF::Draw->color();

ONO::Lib::PDF::Draw->text($canvas,$offset_x+5,$offset_y+16,$num1,"center");
ONO::Lib::PDF::Draw->text($canvas,$offset_x+10,$offset_y+16,$op_symbol,"center");
ONO::Lib::PDF::Draw->text($canvas,$offset_x+15,$offset_y+16,$num2,"center");

if ($mode == 1) {
ONO::Lib::PDF::Draw->text($canvas,$offset_x+20,$offset_y+16,"= $res");
} else {
ONO::Lib::PDF::Draw->text($canvas,$offset_x+20,$offset_y+16,"= ........");
}

}

sub pdf_always {

my (
$self,
$canvas,
$offset_x,
$offset_y,
$res,
$num1,
$num2,
$mode,
$print_num1,
$print_num2,
$symbol1,
$symbol2,
$colors_ref,
$cols,
$corr,
) = @_;

my @colors = @$colors_ref;

if ($mode == 0 || $corr) {
if ($num1 < 11) {
ONO::Lib::PDF::Draw->brick($canvas,$offset_x,$offset_y+3.5,$num1,1,3.5,0.5,$colors[$num1-1]);
} else {
ONO::Lib::PDF::Draw->brick($canvas,$offset_x,$offset_y+3.5,10,1,3.5,0.5,$colors[9]);
ONO::Lib::PDF::Draw->brick($canvas,$offset_x+35,$offset_y+3.5,$num1-10,1,3.5,0.5,$colors[$num1-11]);
}
if (!$corr) {
ONO::Lib::PDF::Draw->rect($canvas,$offset_x+($num1*3.5),$offset_y+3.5,$offset_x+($res*3.5),$offset_y+7,1,"","white:222:222:222");
$print_num2 = ".....";
}

}

if ($mode == 1 || $corr) {

if ($num2 < 11) {
ONO::Lib::PDF::Draw->brick($canvas,$offset_x+($num1*3.5),$offset_y+3.5,$num2,1,3.5,0.5,$colors[$num2-1]);
} else {
ONO::Lib::PDF::Draw->brick($canvas,$offset_x+($num1*3.5),$offset_y+3.5,10,1,3.5,0.5,$colors[9]);
ONO::Lib::PDF::Draw->brick($canvas,$offset_x+($num1*3.5)+35,$offset_y+3.5,$num2-10,1,3.5,0.5,$colors[$num2-11]);
}
if (!$corr) {
ONO::Lib::PDF::Draw->rect($canvas,$offset_x,$offset_y+3.5,$offset_x+$num1*3.5,$offset_y+7,1,"","white:222:222:222");
$print_num1 = ".....";
}

}

ONO::Lib::PDF::Draw->color();

if ($cols == 4) {

ONO::Lib::PDF::Draw->text($canvas,$offset_x,$offset_y+14,"$res","center");
ONO::Lib::PDF::Draw->text($canvas,$offset_x+4,$offset_y+14,$symbol1,"center");
ONO::Lib::PDF::Draw->text($canvas,$offset_x+9,$offset_y+14,$print_num1,"center");
ONO::Lib::PDF::Draw->text($canvas,$offset_x+14,$offset_y+14,$symbol2,"center");
ONO::Lib::PDF::Draw->text($canvas,$offset_x+19,$offset_y+14,$print_num2,"center");

} else {

ONO::Lib::PDF::Draw->text($canvas,$offset_x+5,$offset_y+14,"$res","r");
ONO::Lib::PDF::Draw->text($canvas,$offset_x+7.5,$offset_y+14,$symbol1,"center");
ONO::Lib::PDF::Draw->text($canvas,$offset_x+12.5,$offset_y+14,$print_num1,"center");
ONO::Lib::PDF::Draw->text($canvas,$offset_x+20,$offset_y+14,$symbol2,"center");
ONO::Lib::PDF::Draw->text($canvas,$offset_x+27.5,$offset_y+14,$print_num2,"center");

}

}

sub pdf_mul_info {

my (
$self,
$canvas,
$offset_x,
$offset_y,
$op1,
$op2,
$res,
) = @_;

my $off_y = 3+$op1*3.5;
if ($op1 == 10) {
$off_y = 36;
}
my $add_y;
if ($op1 < 10) {
$add_y = 1.5;
}

ONO::Lib::PDF::Draw->rect($canvas,$offset_x,$offset_y+$off_y,$offset_x+8,$offset_y+$off_y+5+$add_y,1,"0:25:25:25","0:240:240:240",1);

ONO::Lib::PDF::Draw->circle($canvas,$offset_x+10,$offset_y+$off_y+2.5+$add_y/2,0.75,1,1);

ONO::Lib::PDF::Draw->rect($canvas,$offset_x+12,$offset_y+$off_y,$offset_x+20,$offset_y+$off_y+5+$add_y,1,"0:25:25:25","0:240:240:240",1);

ONO::Lib::PDF::Draw->text($canvas,$offset_x+22.25,$offset_y+$off_y+3.5+$add_y/2,"=","c");

ONO::Lib::PDF::Draw->rect($canvas,$offset_x+24.5,$offset_y+$off_y,$offset_x+35,$offset_y+$off_y+5+$add_y,1,"0:25:25:25","0:240:240:240",1);

if ($res) {

ONO::Lib::PDF::Draw->text($canvas,$offset_x+4,$offset_y+$off_y+4+$add_y/2,$op1,"c");
ONO::Lib::PDF::Draw->text($canvas,$offset_x+16,$offset_y+$off_y+4+$add_y/2,$op2,"c");
ONO::Lib::PDF::Draw->text($canvas,$offset_x+30,$offset_y+$off_y+4+$add_y/2,$res,"c");

}

}

sub mul_ops {

my $vars_ref = $_[1];
my %vars = %$vars_ref;

my @ops1 = (1);
if ($vars{'app_input_multiply_mul'}) {
@ops1 = ($vars{'app_input_multiply_mul'});
}
if ($vars{'app_input_multiply_mul'} eq "1_5") {
@ops1 = (1,2,3,4,5);
}
if ($vars{'app_input_multiply_mul'} eq "1_10") {
@ops1 = (1,2,3,4,5,6,7,8,9,10);
}
if ($vars{'app_input_multiply_mul'} eq "2_5") {
@ops1 = (2,5);
}
if ($vars{'app_input_multiply_mul'} eq "2_5_10") {
@ops1 = (2,5,10);
}
my @ops2;
for (my $l = 1; $l < 11; $l++) {
if ($vars{"app_input_mulrow_$l"}) {
@ops2 = (@ops2,$l);
}
}
my $ops1_num = @ops1;
my $ops2_num = @ops2;

if (!$ops2_num) {
@ops2 = (1,2,3,4,5,6,7,8,9,10);
$ops2_num = @ops2;
}

return (\@ops1,\@ops2,$ops1_num,$ops2_num);

}

###################################################################
#### THAT'S IT :-D
###################################################################

1;

__END__