ONO::FW::Edu::Apps::Modules::Random

package ONO::FW::Edu::Apps::Modules::Random;
################################################################################
# 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::FW::User::Init;

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

use ONO::Lib::PDF::Draw;
use ONO::Lib::PDF::ToolBox;
use ONO::Lib::Data::Color;
use ONO::Lib::Data::Letters;
use ONO::Lib::Code::RandomID;

use ONO::Lib::Web::Cookie;
use ONO::FW::Edu::ToolBox;

use ONO::FW::Apps::Core;
use ONO::FW::Apps::Core::Graphics;

use ONO::Lib::Parser;
use ONO::IO;
use ONO::DB;
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;

if (ONO::IO->devstation) {
$vars{'username'} = "jos";
}

my $app = "random";

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

$vars{'app_input_print_options_title_default'} = $BLK{'Random_generator'};

my @letters = ONO::Lib::Data::Letters->get_uc;
my @dicecols = ONO::Lib::Data::Color->dices;

my ($WEB,$workstation_virclass,$force_running);

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

my $cookie = ONO::Lib::Web::Cookie->get("morzino_virclass");
if ($cookie) {
my @cp = split(/-/,$cookie);
my $virclass_dir = ONO::FW::Edu::ToolBox->virclass_dir($cp[0]);
if ($cp[0] && ONO::IO->exists("$virclass_dir/data/computers/$cp[2].txt")) {
my @kp = split(/-/,ONO::IO->load("$virclass_dir/data/computers/$cp[2].txt"));
if ($kp[1] eq $cp[3]) {
unless (
ONO::IO->exists("$virclass_dir/data/computers/$cp[2]_offline.txt") ||
(ONO::IO->exists("$virclass_dir/data/computers/teacher_offline.txt") && $kp[0] eq "teacher") ||
(ONO::IO->exists("$virclass_dir/data/computers/student_offline.txt") && $kp[0] eq "student" )
) {
$workstation_virclass = $cp[0];
}
}
}
}

$workstation_virclass =~ s~[^0-9]~~gi;

}

my @txt = (
"students per group",
);

if ($lang eq "de") {

@txt = (
"Schüler pro Gruppe",
);

}

if ($lang eq "lu") {

@txt = (
"Schüler pro Grupp",
);

}

if ($lang eq "fr") {

@txt = (
"élèves par groupe",
);

}

# instantly generate results in online mode, except for modes that may allow for additional input

if ($vars{'output_web'} && $vars{'app_input_type'} !~ /(no_required_mode_yet)/) {

$force_running++;

}

if (ONO::FW::Apps::Core->running(\%vars,$db) || $force_running) {

$WEB .= ONO::FW::Apps::Core->blockbackbutton($BASE,$vars_ref);

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

#############################################################
# 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'} || $vars{'output_paper'}) {

my ($pdf_align,$num_comma,$num_delimiter,@students,@rands);

my ($max_x,$max_y) = (3,20);
my $pad = "p10";
my $icon_size = 32;

if ($vars{'output_web'}) {
($max_x,$max_y) = (10,5);
}

my ($pdf_x_spacer,$pdf_y_spacer) = (60,0);
my ($pdf_x_offset,$pdf_y_offset);
my $pdf_y_multiplier = 1;

if ($vars{'app_input_type'} eq "numbers") {
$pdf_x_offset = 30;
$pdf_align = "r";
($num_comma,$num_delimiter) = ONO::FW::Apps::Core->local_comma_delimiter(ONO::FW::Apps::Core->detect_local($vars{'app_lang'}),$vars_ref);
}

if ($vars{'app_input_type'} eq "letters") {
@rands = @letters;
$max_x = 10;
$pdf_x_offset = 5;
$pdf_x_spacer = 17.5;
$pdf_align = "c";
}

if ($vars{'app_input_type'} eq "passwords") {
$pad = "p5";
}

if ($vars{'app_input_type'} eq "dices") {
@rands = @dicecols;
$max_x = 6;
$max_y = 10;
if ($vars{'output_web'}) {
$max_x = 5;
$max_y = 5;
}
$pdf_x_spacer = 30;
$pdf_y_multiplier = 2;
}
if ($vars{'app_input_type'} eq "cards") {
@rands = ('c','d','h','s');
$max_x = 5;
$max_y = 5;
if ($vars{'output_web'}) {
$max_y = 2;
}
$pdf_x_spacer = 35;
$pdf_y_multiplier = 4.5;
}
if ($vars{'app_input_type'} eq "students") {
if ($vars{'student_groupnum'} == 2 || $vars{'student_groupnum'} == 4 || $vars{'student_groupnum'} == 8) {
$max_y = 16;
}
if ($vars{'student_groupnum'} == 3 || $vars{'student_groupnum'} == 6 || $vars{'student_groupnum'} == 9) {
$max_y = 18;
}
if ($vars{'student_groupnum'} == 7) {
$max_y = 21;
}
$pad = "p5";
$pdf_x_offset = 10;
}

my $num_rands = @rands;

if ($vars{'app_input_type'} eq "students" && ($vars{'username'} || $workstation_virclass)) {

my $return_dis = 1;

if ($vars{'output_paper'}) {

$return_dis = 0;

}

@students = &get_students("",$db,$community,\%vars,$workstation_virclass,"ORDER BY RAND()",$return_dis);

foreach my $student (@students) {
$vars{'total_students'}++;
my @sp = split(/:/,$student);
if (!$vars{"student_disable_$sp[0]"}) {
$vars{'active_students'}++;
}
}

if ($vars{'output_web'}) {;
if ($vars{'total_students'} > 30) {
$pad = "p2";
if ($vars{'total_students'} > 40) {
$icon_size = 24;
}
}
}

}

my $PDF_OPTS;

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);

}

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

my ($pdf_x,$pdf_y) = (0,3);
my $counter = 0;
my %used;

if ($vars{'output_web'}) {

$WEB .= qq~<$form>
<table class="wide_table">
<tr class="vtop">
~;

}

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::Lib::PDF::ToolBox->canvas_test($canvas);

}

if ($vars{'app_input_type'} eq "students" && $vars{'student_groupnum'} =~ m~^(.*?)x(.*?)/(.*?)x(.*?)$~) {

$vars{'pri_group_num'} = $1;
$vars{'pri_group_max'} = $2;
$vars{'sec_group_num'} = $3;
$vars{'sec_group_max'} = $4;

}

for (my $x = 0; $x < $max_x; $x++) {

$pdf_x = $x * $pdf_x_spacer;
$pdf_y = 3;

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

$counter++;

my $text;

if ($vars{'app_input_type'} eq "numbers") {
$text = $vars{'app_input_range_from'}+int(rand(($vars{'app_input_range_to'}-$vars{'app_input_range_from'})));
if ($vars{'app_input_comma_status'} > 0) {
$text .= $num_comma;
for (my $c = 0; $c < $vars{'app_input_comma_status'}; $c++) {
$text .= int(rand(9));
}
}
}
if ($vars{'app_input_type'} eq "letters") {

if ($counter%$num_rands == 0) {
%used = {};
}
my $whilecounter;
while ((!$text || $used{$text}) && $whilecounter < 100) {
$whilecounter++;
$text = $rands[int(rand($num_rands))];
}
$used{$text}++;

}
if ($vars{'app_input_type'} eq "passwords") {
$text = ONO::Lib::Code::RandomID->make(8);
}
if ($vars{'app_input_type'} eq "dices") {
$text = $rands[int(rand($num_rands))]."_".(1+int(rand(6)));
}
if ($vars{'app_input_type'} eq "cards") {
my $whilecounter;
while ((!$text || $used{$text}) && $whilecounter < 100) {
$whilecounter++;
my $card = 1+int(rand(12));
$card =~ s~10~J~;
$card =~ s~11~K~;
$card =~ s~12~Q~;
$text = $card.$rands[int(rand($num_rands))];
}
$used{$text}++;
}
if ($vars{'app_input_type'} eq "students") {
$text = $students[$counter-1];
}

if ($vars{'output_web'} && $text) {

my ($PRE1,$PRE2,$STYLE);

if ($vars{'app_input_type'} eq "passwords") {
$text = qq~<input type="text" name="" value="$text" class="w90 auto" onclick="this.select();">~;
}
if ($vars{'app_input_type'} eq "dices") {
$text = qq~<img class="block64 auto" src="/ono/osr/images/dices/64/$text.jpg" alt="">~;
}
if ($vars{'app_input_type'} eq "cards") {
$text = qq~<div class="mt20"><div class="bo radius5 p2 auto" style="width:96px"><img class="block96" src="/images/cards/$text.jpg" style="height:135px" alt=""></div></div>~;
}
if ($vars{'app_input_type'} eq "students") {

my @sp = split(/:/,$text);

my $TRANS;
if ($vars{"student_disable_$sp[0]"}) {
if (!$vars{'student_disabled_detected'}) {
$vars{'students_in_one_line'} = 0;
$WEB .= &group_line("",qq~<div class="mt20 lightred">$BLK{'Disabled'}</div>~);
}
$vars{'student_disabled_detected'}++;
$TRANS = " trans30";
} else {
# $vars{'active_students'}++;
}

my $SWITCH = ONO::Lib::UI::Check->switch("student_disable_$sp[0]",$vars{"student_disable_$sp[0]"},"im");

my $WIDTH = 20;
if ($vars{'student_groupnum'} > 1 || $vars{'pri_group_num'}) {

if (!$vars{'student_groupnum_counter'}) {
$vars{'student_groupnum_counter'} = 1;
$WEB .= &group_line("","$BLK{'Group'} $vars{'student_groupnum_counter'}");
}

if ($vars{'student_groupnum'} < 5) {
$WIDTH = int(100/$vars{'student_groupnum'});
}
if ($vars{'pri_group_num'}) {
$WIDTH = int(100/$vars{'pri_group_max'});
}
}

$STYLE = "width:$WIDTH\%";

my $PROIMG = ONO::FW::User::Init->profileimage($sp[0],32);
$PRE1 = qq~<td class="p5$TRANS">$PROIMG</td>~;
$PRE2 = qq~<td class="p5 cola tar" style="padding-right:0px"><div class="lh125$TRANS"><div class="large">$counter.</div></div>$SWITCH</td>~;
$text = qq~<a href="/users/$sp[0]/" target="_parent"><div class="lh125 tal$TRANS"><div class="large col3">$sp[1]</div><div class="cola small">$sp[0]</div></div></a>~;
if ($icon_size == 24) {
$PRE2 = qq~<td class="p5 cola tar" style="padding-right:0px"><div class="lh125$TRANS">$counter.</div>$SWITCH</td>~;
$text = qq~<a href="/users/$sp[0]/" target="_parent"><div class="lh125 tal col3$TRANS">$sp[1]</div></a>~;
}

$vars{'students_in_one_line'}++;
$vars{'diplayed_students'}++;

# if (ONO::IO->devstation) {
# $WEB .= qq~<td>$vars{'students_in_one_line'}</td>~;
# }

if ($vars{'student_groupnum'} > 1 && $vars{'students_in_one_line'} > 5) {
$vars{'students_in_one_line'} = 1;
$WEB .= qq~</tr><tr class="vtop">~;
}

# $WEB.=qq~<br>$vars{'student_groupnum'},$vars{'students_in_one_line'},~;

if ($vars{'pri_group_num'} && $vars{'students_in_one_line'}%5 == 0) {
# $vars{'students_in_one_line'} = 0;
$WEB .= qq~</tr><tr class="vtop">~;
}
}

$WEB .= qq~$PRE1$PRE2<td class="$pad w20 center" style="$STYLE">$text</td>~;

my $disable_linebreak;

if ($vars{'student_groupnum'} > 1 || $vars{'pri_group_num'}) {
$disable_linebreak++;
}

if ($counter%5 == 0 && !$disable_linebreak) {
$WEB .= qq~</tr><tr class="vtop">~;
}

# student groups logic:

my $groupnum_checker = $vars{'student_groupnum'};
if ($vars{'pri_group_num'}) {
$groupnum_checker = $vars{'pri_group_max'};
if ($vars{'student_groupnum_counter'} > $vars{'pri_group_num'}) {
$groupnum_checker = $vars{'sec_group_max'};
}
}

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

if (($vars{'student_groupnum'} > 1 || $vars{'pri_group_num'}) && $counter%$groupnum_checker == 0) {

$vars{'student_groupnum_counter'}++;

if ($vars{'student_disabled_detected'}) {

$vars{'students_in_one_line'} = 0;
$WEB .= &group_line("","");

} else {

if (!$vars{'pri_group_num'}) {

if ($vars{'diplayed_students'} < $vars{'active_students'}) {

$vars{'students_in_one_line'} = 0;
$WEB .= &group_line("",qq~<div class="mt20">$BLK{'Group'} $vars{'student_groupnum_counter'}</div>~);

}

} else {

if ($vars{'student_groupnum_counter'} < $vars{'pri_group_num'}+2) {

$vars{'students_in_one_line'} = 0;
$WEB .= &group_line("",qq~<div class="mt20">$BLK{'Group'} $vars{'student_groupnum_counter'}</div>~);

}

}

}

}

if ($vars{'student_groupnum_counter'} > $vars{'pri_group_num'} && $vars{'students_in_one_line'} > $groupnum_checker-1 && $vars{'diplayed_students'} < $vars{'active_students'}) {

$vars{'students_in_one_line'} = 0;
$WEB .= &group_line("",qq~<div class="mt20">$BLK{'Group'} $vars{'student_groupnum_counter'}</div>~);

}

}

}

if ($vars{'output_paper'}) {

if ($text && $vars{'app_input_type'} =~ /(numbers|letters|passwords|students)/) {
if ($vars{'app_input_type'} eq "students") {
ONO::Lib::PDF::Draw->text($canvas,$pdf_x+$pdf_x_offset-2,$pdf_y+$pdf_y_offset,"$counter.","r");
$text =~ s~^(.*):~~;
}
ONO::Lib::PDF::Draw->text($canvas,$pdf_x+$pdf_x_offset,$pdf_y+$pdf_y_offset,$text,$pdf_align);
}

if ($vars{'app_input_type'} eq "dices") {
ONO::Lib::PDF::Draw->image($canvas,$pdf_x+$pdf_x_offset,$pdf_y*$pdf_y_multiplier-3,12,12,"/ono/osr/images/dices/64/$text.jpg");
}
if ($vars{'app_input_type'} eq "cards") {
ONO::Lib::PDF::Draw->image($canvas,$pdf_x+$pdf_x_offset,$pdf_y*$pdf_y_multiplier-10,22.5,31.5,"/images/cards/$text.jpg",1);
}

my $group_limit = 5;

if ($vars{'student_groupnum'} > 1) {
$group_limit = $vars{'student_groupnum'};
}

$pdf_y = $pdf_y + 8.4;
if (($y+1)%$group_limit == 0) {
$pdf_y = $pdf_y + 8.4;
}

if ($pdf_y > 200) {
$pdf_x = $pdf_x + $pdf_x_spacer;
$pdf_y = 3;
}

}

}
}

}

if ($vars{'output_web'}) {

my $OPTS;

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

my $SEL = &group_select("",$vars{'student_groupnum'},$vars{'active_students'},$BLK{'groups'},$txt[0]);

$OPTS = qq~<td>
$SEL
</td>
~;

}

my $INPUT = ONO::FW::Apps::Core->input_vars($vars_ref);

$WEB .= qq~ </tr>
</table>

$INPUT
<div class="inline auto">
<table class="default_table mt10">
<tr>
$OPTS
<td><input type="submit" name="output_web_again" value="$BLK{'again'}" class="button_green"></td>
</tr>
</table>
</div>
</form>
~;

}

if ($vars{'output_paper'}) {

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

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

}

}

} else {

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

my $JS1 = qq~onojs_class('ono_fwapps_input_row_range','');onojs_class('ono_fwapps_input_row_comma','');~;
my $JS2 = qq~onojs_class('ono_fwapps_input_row_range','trans50');onojs_class('ono_fwapps_input_row_comma','trans50');onojs_class('ono_fwapps_input_row_select','trans50');~;
my $JS2a = qq~$JS2;onojs_ui_radio_app_input_type_select('letters','button_green','bg_paper');~;
my $JS2b = qq~$JS2;onojs_ui_radio_app_input_type_select('passwords','button_green','bg_paper');~;
my $JS2c = qq~$JS2;onojs_ui_radio_app_input_type_select('dices','button_green','bg_paper');~;
my $JS2d = qq~$JS2;onojs_ui_radio_app_input_type_select('cards','button_green','bg_paper');~;
my $JS2e = qq~$JS2;onojs_ui_radio_app_input_type_select('students','button_green','bg_paper');onojs_class('ono_fwapps_input_row_select','');~;

my @opts = (
"numbers;$JS1",
"letters;$JS2a",
"passwords;$JS2b",
"dices;$JS2c",
"cards;$JS2d",
"students;$JS2e",
);
my $sel = "numbers";
if ($vars{'app_input_type'} =~ /^(letters|passwords|dices|cards|students)$/) {
$sel = $1;
}

my ($trans_numbers,$trans_students);
if ($vars{'app_input_type'}) {
if ($vars{'app_input_type'} ne "numbers") {
$trans_numbers = "t";
}
if ($vars{'app_input_type'} ne "students") {
$trans_students = "t";
}
} else {
$trans_students = "t";
}

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

my ($STUDENTS,$STUDENT_LIST,%used);

if ($vars{'username'} || $workstation_virclass) {

if ($vars{'username'}) {

foreach my $line (ONO::DB->select($db,"${community}_school_virclass_relationships","username = '$vars{'username'}' AND status = '1'")) {
my @col = ONO::DB->readcols($line);

foreach my $line2 (ONO::DB->select($db,"${community}_school_virclass","id = '$col[2]'")) {
my @col2 = ONO::DB->readcols($line2);

if (!$used{$col2[0]} && $col2[17] !~ /H/) {
$used{$col2[0]}++;
$col2[6] =~ s~(=|;)~~g;
my $num = ONO::DB->count($db,"${community}_school_virclass_relationships","virclass = '$col2[0]' AND type = 'student' AND status = '1'");
if ($num) {
$STUDENT_LIST .= qq~$col2[0]=$col2[6] ($num);~;
}

}
}
}
}

if ($workstation_virclass) {

foreach my $line2 (ONO::DB->select($db,"${community}_school_virclass","id = '$workstation_virclass'")) {
my @col2 = ONO::DB->readcols($line2);

if (!$used{$col2[0]} && $col2[17] !~ /H/) {
$used{$col2[0]}++;
$col2[6] =~ s~(=|;)~~g;
my $num = ONO::DB->count($db,"${community}_school_virclass_relationships","virclass = '$col2[0]' AND type = 'student' AND status = '1'");
if ($num) {
$STUDENT_LIST .= qq~$col2[0]=$col2[6] ($num);~;
}

}
}

}

if ($STUDENT_LIST) {

$STUDENTS .= ONO::FW::Apps::ToolBox->conf_input("custom", $BLK_ref,\%vars,"",$RADIO[6],qq~<div class="cursorlink" onclick="$JS2e">$BLK{'Students'}:</div>~);
$STUDENTS .= ONO::FW::Apps::ToolBox->conf_input("select", $BLK_ref,\%vars,"I$trans_students",$STUDENT_LIST,"",$vars{'app_input_select'},$JS2e);

}
}

my @TXT = (
qq~<div class="cursorlink" onclick="$JS1">$BLK{'Numbers'}:</div>~,
qq~<div class="cursorlink" onclick="$JS2a">$BLK{'Letters'} <span class="col9 small">(A-Z)</span></div>~,
qq~<div class="cursorlink" onclick="$JS2b">$BLK{'Passwords'} <span class="col9 small">(8 $BLK{'chars'}: A-Z, a-z, 0-9)</div></div>~,
qq~<div class="cursorlink" onclick="$JS2c">$BLK{'Dices'}</div>~,
qq~<div class="cursorlink" onclick="$JS2d">$BLK{'Cards'}</div>~,

);

my $CONF;

my $student_pdf_mode;

if ($vars{'output_paper'} && $vars{'app_input_type'} eq "students") {
$student_pdf_mode++;
}

if (!$student_pdf_mode) {

$CONF .= ONO::FW::Apps::ToolBox->conf_input("custom", $BLK_ref,\%vars,$trans_numbers,$RADIO[1],$TXT[0]);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("range", $BLK_ref,\%vars,"IN$trans_numbers",1,999999,100);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("comma", $BLK_ref,\%vars,"IC$trans_numbers",3,"","","$BLK{'comma'}:");
$CONF .= ONO::FW::Apps::ToolBox->conf_input("custom", $BLK_ref,\%vars,"",$RADIO[2],$TXT[1]);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("custom", $BLK_ref,\%vars,"",$RADIO[3],$TXT[2]);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("custom", $BLK_ref,\%vars,"",$RADIO[4],$TXT[3]);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("custom", $BLK_ref,\%vars,"",$RADIO[5],$TXT[4]);

}

$CONF .= $STUDENTS;

if ($student_pdf_mode) {

my $SEL = &group_select("",$vars{'student_groupnum'},$vars{'active_students'},$BLK{'groups'},$txt[0]);

$CONF .= ONO::FW::Apps::ToolBox->conf_input("custom", $BLK_ref,\%vars,"","",$SEL);

if ($vars{'username'} || $workstation_virclass) {

my $LIST;

foreach my $student (&get_students("",$db,$community,\%vars,$workstation_virclass,"realname,username",1)) {

my @sp = split(/:/,$student);

my $SWITCH = ONO::Lib::UI::Check->switch("student_disable_$sp[0]",0,"im");

$LIST .= qq~<tr><td>$SWITCH</td><td>$sp[1]</td></tr>~;

}

$LIST = qq~<div class="box_paper p0 mt5" style="height:220px;overflow-x:hidden;overflow-y:scroll"><table class="default_table">$LIST</table></div>~;

$CONF .= ONO::FW::Apps::ToolBox->conf_input("custom", $BLK_ref,\%vars,"","",$LIST);

}

}

$CONF .= ONO::FW::Apps::ToolBox->conf_input("spacer", $BLK_ref,\%vars);
# if ($vars{'output_paper'}) {
# $CONF .= ONO::FW::Apps::ToolBox->conf_input("selnum", $BLK_ref,\%vars,"",1,1,"dDr");
# } else {
# $CONF .= ONO::FW::Apps::ToolBox->conf_input("selnum", $BLK_ref,\%vars,"",1,100,"dr");
# }
$CONF .= $RADIO[0];

$vars{'output_paper_custom_text'} = $BLK{'print'};
$vars{'output_web_custom_text'} = "$BLK{'generate'} ($BLK{'online'})";

# uses a cached file in 99% of all cases, or re-creates a random background and caches it.

my $CACHE = "apps-morzino-random-preview-".int(rand(100));

if ($vars{'apps_morzino_random_preview_id'}) {
$CACHE = $vars{'apps_morzino_random_preview_id'};
}
$CONF .= qq~<input type="hidden" name="apps_morzino_random_preview_id" value="$CACHE">~;

my $RAND = ONO::IO->cachereadsimple($CACHE);

if (!$RAND || int(rand(100)) == 50) { # || ONO::IO->devstation) {

for (my $i = 0; $i < 100; $i++) {
my $top = int(rand(400))."px";
my $right = int(rand(900))."px";
my $size = 12+int(rand(24));
my $rot = (int(rand(60))-30)."deg";
my ($a,$b,$c) = (1+int(rand(9)),1+int(rand(9)),1+int(rand(9)));
my $type = int(rand(5));
my $RES;
if ($type == 0) {
my $n = int(rand(1000));
$RES .= qq~<div class="box_paper radius5" style="font-size:${size}px;color:#$a$a$b$b$c$c">$n</div>~;
}
if ($type == 1) {
my $n = int(rand(26));
$RES .= qq~<div class="box_paper radius5" style="font-size:${size}px;color:#$a$a$b$b$c$c">$letters[$n]</div>~;
}
if ($type == 2) {
my $num = @dicecols;
my $n = $dicecols[int(rand($num))]."_".(1+int(rand(6)));
$size = $size*2;
$RES .= qq~<div class="block64 radius10" style="width:${size}px;height:${size}px;overflow:hidden">
<img class="block radius10" src="/ono/osr/images/dices/64/$n.jpg" style="width:${size}px;height:${size}px" alt="">
</div>
~;
}
if ($type == 3) {
my @cols = ('c','d','h','s');
my $card = 1+int(rand(12));
$card =~ s~10~J~;
$card =~ s~11~K~;
$card =~ s~12~Q~;
$card .= $cols[int(rand(4))];
my ($w,$h) = (int(96/$a)*2,int(135/$a)*2);
$RES .= qq~<div class="box_paper radius5 p2 auto" style="width:${w}px"><img class="block" src="/images/cards/$card.jpg" style="width:${w}px;height:${h}px" alt=""></div>~;
}
$RAND .= qq~<div class="abs" style="top:$top;right:$right;-ms-transform:rotate($rot);-webkit-transform:rotate($rot);transform:rotate($rot)">$RES</div>~;

}

ONO::IO->cachewritesimple($CACHE,$RAND);

}

$WEB .= qq~<div class="rel fr hide720" style="width:920px;height:480px;overflow:hidden;background-image:url('/images/app_backgrounds/math_games_green.jpg')">$RAND</div>~;

$WEB .= ONO::FW::Apps::Core->conf_box(
$db,
$community,
$app,
$form,
"",
$action_url,
$CONF,
$lang,
$BLK_ref,
\%vars,
"S-op-nd-CD-TL",
);

}

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;

}

sub group_select {

my (
$self,
$selected,
$active_students,
$groups,
$txt,
) = @_;

my ($GROUPS,$BEST,@SPECIAL);

# from 3 to up to 10

if ($active_students == 10) {
$BEST = qq~<option value="5">2 x 5</option>~;
@SPECIAL = (
"2x3/2x2",
"1x4/2x3",
"1x6/1x4",
);
}

if ($active_students == 11) {
$BEST = qq~<option value="6">6 + 5</option>~;
@SPECIAL = (
"1x3/4x2",
"3x3/1x2",
"2x4/1x3",
"1x5/2x3",
);
}

if ($active_students == 12) {
$BEST = qq~<option value="6">2 x 6</option>
<option value="4">3 x 4</option>
<option value="3">4 x 3</option>
~;
@SPECIAL = (
"2x5/1x2",
"1x7/1x5",
);
}

if ($active_students == 13) {
$BEST = qq~<option value="7">7 + 6</option>~;
@SPECIAL = (
"1x4/3x3",
"1x5/2x4",
"2x5/1x3",
);
}

if ($active_students == 14) {
$BEST = qq~<option value="7">2 x 7</option>~;
@SPECIAL = (
"3x4/1x2",
"4x3/1x2",
"1x5/3x3",
"2x5/1x4",
);
}

if ($active_students == 15) {
$BEST = qq~<option value="8">8 + 7</option>~;
@SPECIAL = (
"3x4/1x3",
"2x6/1x3",
);
}

if ($active_students == 16) {
$BEST = qq~<option value="4">4 x 4</option>~;
@SPECIAL = (
"2x5/2x3",
);
}

if ($active_students == 17) {
$BEST = qq~<option value="8">8 + 7</option>~;
@SPECIAL = (
"1x5/3x4",
"2x4/3x3",
);
}

if ($active_students == 18) {
$BEST = qq~<option value="6">3 x 6</option>~;
@SPECIAL = (
"3x4/2x3",
"2x5/2x4",
"3x5/1x3",
);
}

if ($active_students == 19) {
@SPECIAL = (
"3x5/1x4",
"4x4/1x3",
"1x4/5x3",
);
}

if ($active_students == 20) {
$BEST = qq~<option value="5">4 x 5</option>
<option value="4">5 x 4</option>
~;
@SPECIAL = (
"3x6/1x2",
"6x3/1x2",
);
}

if ($active_students == 21) {
$BEST = qq~<option value="7">3 x 7</option>
<option value="3">7 x 3</option>
~;
@SPECIAL = (
"1x5/4x4",
"2x6/3x3",
);
}

if ($active_students == 22) {
$BEST = qq~<option value="11">2 x 11</option>~;
@SPECIAL = (
"2x6/2x5",
"3x6/1x3",
"4x5/1x2",
);
}

if ($active_students == 23) {
@SPECIAL = (
"3x6/1x5",
"4x5/1x3",
"5x4/1x3",
);
}

if ($active_students == 24) {
$BEST = qq~<option value="6">4 x 6</option>
<option value="12">2 x 12</option>
~;
@SPECIAL = (
"4x5/1x4",
"1x4/5x3",
);
}

if ($active_students == 25) {
$BEST = qq~<option value="5">5 x 5</option>~;
@SPECIAL = (
"1x7/3x6",
"1x5/5x4",
);
}

if ($active_students == 26) {
$BEST = qq~<option value="13">2 x 13</option>~;
@SPECIAL = (
"1x8/3x6",
"2x7/2x6",
"1x6/4x5",
"1x6/5x4",
"3x6/2x4",
"4x5/2x3",
"5x4/2x3",
);
}

if ($active_students == 27) {
$BEST = qq~<option value="9">3 x 9</option>
<option value="3">9 x 3</option>
~;
@SPECIAL = (
"4x6/1x3",
"5x5/1x2",
"6x4/1x3",
);
}

if ($active_students == 28) {
$BEST = qq~<option value="7">4 x 7</option>
<option value="4">7 x 4</option>
~;
@SPECIAL = (
"4x6/1x4",
"5x5/1x3",
"6x4/1x4",
"1x4/8x3",
);
}

if ($active_students == 29) {
@SPECIAL = (
"4x6/1x5",
"5x5/1x4",
"1x5/8x3",
"6x4/1x5",
);
}

if ($active_students == 30) {
$BEST = qq~<option value="6">5 x 6</option>
<option value="5">6 x 5</option>
<option value="3">10 x 3</option>
~;
@SPECIAL = (
"7x4/1x2",
);
}

foreach my $SPE (@SPECIAL) {
$SPE =~ m~^(.*?)x(.*?)/(.*?)x(.*?)$~;
my $sel;
if ($selected eq "${1}x${2}/${3}x${4}") {
$sel = " selected";
}
$GROUPS .= qq~ <option value="${1}x${2}/${3}x${4}"$sel>($1 x $2) + ($3 x $4) </option>~;
}

if ($GROUPS) {
$GROUPS .= qq~ <option value="">----</option>~;
}
if ($BEST) {
$BEST .= qq~ <option value="">----</option>~;
}

for (my $i = 2; $i < 11; $i++) {
my $sel;
if ($i eq $selected) {
$sel = " selected";
}
$GROUPS .= qq~ <option value="$i"$sel>$i $txt</option>~;
}

return qq~<div class="select"><select name="student_groupnum">
<option value="">$groups:</option>
<option value="">----</option>
$BEST
$GROUPS
</select></div>
~;

}

sub group_line {

return qq~</tr><tr><td></td><td></td><td><div class="large bold lightgreen p2">$_[1]</div></td></tr><tr class="vtop">~;

}

sub get_students {

my (
$self,
$db,
$community,
$vars_ref,
$workstation_virclass,
$ORDER,
$return_dis,
) = @_;

my %vars = %$vars_ref;

my $app_input_select = $vars{'app_input_select'};
$app_input_select =~ s~[^0-9]~~g;

my (@students,@students_dis);

if ($vars{'username'}) {

my $found;

foreach my $line (ONO::DB->select($db,"${community}_school_virclass_relationships","username = '$vars{'username'}' AND virclass = '$app_input_select' AND status = '1'")) {
my @col = ONO::DB->readcols($line);

# $found makes sure we'll only do this once

if (!$found) {
$found++;
foreach my $line (ONO::DB->select($db,"${community}_school_virclass_relationships","virclass = '$app_input_select' AND type = 'student' AND status = '1'",$ORDER)) {
my @col = ONO::DB->readcols($line);
if (!$col[5]) {
$col[5] = ucfirst $col[1];
}
if ($vars{"student_disable_$col[1]"}) {
@students_dis = (@students_dis,"$col[1]:$col[5]");
} else {
@students = (@students,"$col[1]:$col[5]");
}
}
}
}
}

if ($workstation_virclass) {
foreach my $line (ONO::DB->select($db,"${community}_school_virclass_relationships","virclass = '$workstation_virclass' AND type = 'student' AND status = '1'",$ORDER)) {
my @col = ONO::DB->readcols($line);
if (!$col[5]) {
$col[5] = ucfirst $col[1];
}
if ($vars{"student_disable_$col[1]"}) {
@students_dis = (@students_dis,"$col[1]:$col[5]");
} else {
@students = (@students,"$col[1]:$col[5]");
}
}
}

if ($return_dis) {

return (@students,sort @students_dis);

} else {

return @students;

}

}

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

1;

__END__