ONO::FW::Edu::Apps::Modules::CrossWords

package ONO::FW::Edu::Apps::Modules::CrossWords;
################################################################################
# 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::Edu::Apps::Variation;

use ONO::Lib::Encoding::HTML;

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

use ONO::Lib::PDF::Draw;
use ONO::Lib::PDF::ToolBox;

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

use ONO::Lib::Parser;
use ONO::FW::Apps::PDF;
use ONO::IO;

use ONO::DB;
use ONO::Lib::SQL::TableCreate;
use ONO::Lib::Basic;
use ONO::Lib::Lang::ToolBox;
use ONO::Lib::Data::Letters;

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

my $WEB;

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

my $NAME = ucfirst $BLK{$app};

$vars{'app_input_print_options_title_default'} = $NAME;

#

my @txt = (
"display images",
"add page with larger images",
"print words below images",
"Not all images on this page will necessarily be used in the exercise!",
);
if ($lang eq "de") {
@txt = (
"Bilder anzeigen",
"Seite mit größeren Bildern hinzufügen",
"Wörter unter Bilder drucken",
"Eventuell werden nicht alle Bilder auf dieser Seite in der Übung verwendet!",
);
}

if ($lang eq "fr") {
@txt = (
"afficher des images",
"ajouter une page avec des images plus grandes",
"mots en dessous des images",
"Toutes les images de cette page ne seront pas nécessairement utilisées dans l'exercice!",
);
}

if ($lang eq "lu") {
@txt = (
"Biller uweisen",
"Säit mat gréissere Biller bäimaachen",
"Wierder ënnert de Biller",
"Eventuell gi net all Biller op dëser Säit onbedéngt an der Übung benotzt!",
);
}

#

my $total_pix = ONO::FW::Apps::Core::Lang->total_pix();

if (ONO::IO->devstation) {
$vars{'username'} = "jos";
}
if (ONO::FW::Apps::Core->running(\%vars,$db) && ($vars{'output_web'} || $vars{'output_paper'})) {
$vars{'wordlist_force_loading'} = 1;
}

$vars{'app_input_langs_lang_2'} = "img";

my (
$RETURN,$WORDLIST_ref,$TRANS_ref,$IMGS_ref,
$USE_GROUPS,$USE_GROUPS_ALT,$USE_GROUPS_LU,$USE_GROUPS_CUSTOM_ref,
$CACHE_WORDS,$CACHE_TRANS,$CACHE_IMGS,
$use_language1,$use_language2,
$use_images,$use_images_reverse,$use_images_forced,$use_custom_groups,$use_lu,
$get_words,$words_found,$multi_frame_custom_width,$hide_flags,
) = ONO::FW::Apps::Core::Lang->lang_load_wordlist($db,$community,\%vars);

$WEB .= $RETURN;
my @WORDLIST = @$WORDLIST_ref;
my @TRANS = @$TRANS_ref;
my @IMGS = @$IMGS_ref,
my @USE_GROUPS_CUSTOM = @$USE_GROUPS_CUSTOM_ref;

$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) && $words_found) || $vars{'output_web_crosswords_code'}) {

#############################################################
# WORKSHEET MAKER
#############################################################

if ($vars{'output_worksheet_maker'}) {

$vars_ref = ONO::FW::Edu::Apps::Modules::WorksheetMaker::Input->vars(\%vars);
%vars = %$vars_ref;

}

#############################################################
# ONLINE TRAINING
#############################################################

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

if ($vars{'output_web'} || $vars{'output_paper'}) {

if ($vars{'output_web_mc_continue'} || $vars{'output_web_continue_key'} || $vars{'output_web_continue_key_mistake'}) {
$vars{'output_web_question_number'}++;
}
if ($vars{'output_web_continue_key_mistake'}) {
$vars{'output_web_mistakes'}++;
}

if ($vars{"output_web_continue"}) {
foreach my $key (keys %vars) {
if ($key =~ /^output_web_answer_/) {
$vars{$key} = "";
}
}
}

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

if ($vars{'app_input_number_of_questions'} > $words_found) {
$vars{'app_input_number_of_questions'} = $words_found;
}

my (
$focus_on,$page,$pages,%cache,$whilecounter,$stats_switches,$PDF_OPTS,
$stat_correct,$stat_wrong,$stat_todo,$stat_todo_total,@letters_lc,@letters_uc,$longest_word,
);

my $questions_per_page = 20;

if ($vars{'output_paper'} && $vars{'output_web_crosswords_code'}) {

$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 $copy = 1;

my @corr_cache;
my $AUTO_SUBMIT;

if ($vars{'output_paper'}) {

if ($copy > 1) {
@WORDLIST = ONO::Lib::Basic->randomize_array(@WORDLIST);
}

$WEB .= qq~<$form>
<input type="hidden" name="output_web_cache_words" value="$CACHE_WORDS">
<input type="hidden" name="output_web_cache_trans" value="$CACHE_TRANS">
<input type="hidden" name="output_web_cache_imgs" value="$CACHE_IMGS">
~;

if ($vars{'output_web_crosswords_code'}) {

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

my ($rows_num,$cols_num,%grid,$rot,$images_num);

my @rows = split(/;/,$vars{'output_web_crosswords_code'});
my $DEBUG .= qq~<table class="default_table">~;

# first we will simply analyze the code and find col and row lengths (be careful with umlauts!),
# and we'll put all letters in a GRID hash...

foreach my $line (@rows) {
$rows_num++;
$DEBUG .= qq~<tr class="">~;
my $letter_num;
foreach my $letter (ONO::Lib::Basic->umlaut_string_to_array($line)) {
$letter_num++;
if ($rows_num == 1) {
$cols_num++;
}
$grid{"$rows_num,$letter_num"} = $letter;
$DEBUG .= qq~<td class="p0 bt bb bl br"><div class="block24 center">$letter</div></td>~;
}
$DEBUG .= qq~</tr>~;
}
$DEBUG .= qq~</table>~;

# generate image list

my %images;
foreach my $image (split(/;/,$vars{'output_web_cache_images'})) {
my @ip = split(/:/,$image);
$images{$ip[0]} = $ip[1];
$images_num++;
}

# now let's see if we need to rotate the grid...

if ($cols_num > $rows_num) {

# case 1 of 2: rotate

$DEBUG .= qq~ROTATE<table class="default_table">~;

my $size_c = int(190/($cols_num+1));
my $size_r = int(170/($rows_num+1));
my $size = $size_c;
if ($size_c < $size_r) {
$size = $size_c;
}
my $off_x = (170-$rows_num*$size)/2;

for (my $c = $cols_num; $c > 0 ; $c--) {
$DEBUG .= qq~<tr class="">~;
for (my $r = 1; $r < $rows_num+1; $r++) {
my ($g,$x,$y,$s) = ($grid{"$r,$c"},($r-1)*$size+$off_x,($c-1)*$size,$size);
&print_box("",$canvas,$g,$x,$y,$s,\%images,"h",$vars{'username'},$community);
@corr_cache = (@corr_cache,"$g:$x:$y:$s");
$DEBUG .= qq~<td class="p0 bt bb bl br"><div class="block24 center">$grid{"$r,$c"}</div></td>~;
}
$DEBUG .= qq~</tr>~;
}
$DEBUG .= qq~</table>~;

} else {

# case 2 of 2: don't rotate

$DEBUG .= qq~NORMAL<table class="default_table">~;

my $size_c = int(170/$cols_num);
my $size_r = int(190/$rows_num);
my $size = $size_c;
if ($size_r < $size_c) {
$size = $size_r;
}

my $off_x = (170-$cols_num*$size)/2;

for (my $r = 1; $r < $rows_num+1; $r++) {
$DEBUG .= qq~<tr class="">~;
for (my $c = 1; $c < $cols_num+1; $c++) {
my ($g,$x,$y,$s) = ($grid{"$r,$c"},($c-1)*$size+$off_x,($r-1)*$size,$size);
&print_box("",$canvas,$g,$x,$y,$s,\%images,"h",$vars{'username'},$community);
@corr_cache = (@corr_cache,"$g:$x:$y:$s");
$DEBUG .= qq~<td class="p0 bt bb bl br"><div class="block24 center">$grid{"$r,$c"}</div></td>~;
}
$DEBUG .= qq~</tr>~;
}
$DEBUG .= qq~</table>~;
}

$DEBUG .= qq~<br>rows: $rows_num, cols: $cols_num, rot: $rot<br>~;

if (ONO::IO->devstation) {
# $WEB.=$DEBUG;
}

if ($vars{'app_input_display_images_large'}) {

ONO::FW::Apps::PDF->page("",$format);
ONO::FW::Apps::Core->headers($vars_ref,$format);
ONO::FW::Apps::PDF->title($vars{'app_input_print_options_title'},$PDF_OPTS,$vars{'app_input_print_options_code'},$format);
# ONO::Lib::PDF::ToolBox->canvas_test($canvas);

my ($pos_x,$pos_y) = (10,0);
my $img_size = 320/$images_num;
if ($img_size > 40) {
$img_size = 40;
}

my %words;
if ($vars{'app_input_display_images_words'}) {
foreach my $key (split(/;;/,$vars{'output_web_cache_words'})) {
my @kp = split(/;/,$key);
$words{$kp[0]} = $kp[1];
}
}

foreach my $key (ONO::Lib::Data::Letters->get_uc()) {

# $WEB.=qq~<br>xx:$images{$key}~;

if ($images{$key} =~ /[0-9]/) {

my $IMG_URL = ONO::FW::Apps::Core::Lang->lang_image_url_generator($images{$key},$vars{'username'},$community);

ONO::Lib::PDF::Draw->image($canvas,$pos_x,$pos_y,$img_size,$img_size,$IMG_URL,1,2);

ONO::Lib::PDF::Draw->circle($canvas,$pos_x+2,$pos_y+2,3,1,"0:150:50:50");
ONO::Lib::PDF::Draw->font("HB",10);
ONO::Lib::PDF::Draw->color(200,200,200);
ONO::Lib::PDF::Draw->text($canvas,$pos_x+2,$pos_y+3,$key,"c");
ONO::Lib::PDF::Draw->font("H",12);
ONO::Lib::PDF::Draw->color();

if ($vars{'app_input_display_images_words'}) {

ONO::Lib::PDF::Draw->text($canvas,$pos_x+$img_size/2,$pos_y+$img_size+5,$words{$images{$key}},"c");

}

$pos_x = $pos_x + $img_size*2;
if ($pos_x > 160-$img_size) {
$pos_x = 10;
$pos_y = $pos_y + $img_size*1.5 + 5;
}
}
}

ONO::Lib::PDF::Draw->text($canvas,0,190,$txt[3]);

}

if (ONO::FW::Apps::Core->print_corrections("$BASE/pdf/pdf-$pdfkey-corr.pdf","",$format,$vars_ref)) {

ONO::FW::Apps::Core->headers($vars_ref,$format,"c");
ONO::FW::Apps::PDF->title($BLK{'Corrections'},$PDF_OPTS,$vars{'app_input_print_options_code'},$format);
# ONO::Lib::PDF::ToolBox->canvas_test($canvas);

foreach my $cache (@corr_cache) {

my @cp = split(/:/,$cache);
&print_box("",$canvas,$cp[0],$cp[1],$cp[2],$cp[3],\%images,"",$vars{'username'},$community);

}

}


} else {

my ($CROSSWORDS,$IMAGES,$found);
my $display_words = 20;
my ($max_x,$max_y) = (12,12);
my @letter_num = ONO::Lib::Data::Letters->get_uc();

for (my $i = 0; $i < 20; $i++) {

if (ONO::IO->devstation) {
if ($WORDLIST[$i]) {
# $WEB .= qq~WORD -> $WORDLIST[$i]<br>~;
}
}

my ($img,$word) = split(/\^/,$WORDLIST[$i]);

if ((($img =~ /[0-9]/ && $img !~ /[A-Za-z]/) || $img =~ m~^media/~) && $word && $found < $display_words && (length $word < $max_x || length $word < $max_y)) {
$word = ONO::Lib::Lang::ToolBox->remove_article($word);
if ($word !~ m~ ~) {
$found++;
$CROSSWORDS .= $letter_num[$found-1].lc $word.",";
$IMAGES .= "$letter_num[$found-1]:$img;";
# $WORDS .= "$letter_num[$found-1]:$word;";
}
}

}

$CROSSWORDS =~ s~\,$~~;

my $dev_disable;

#$dev_disable++;

if (ONO::IO->devstation && $dev_disable) {

$WEB .= "DEV DISABLED<br><br>$CROSSWORDS<br><br>$IMAGES";

} else {

$WEB .= qq~<div class="p20">
<h2>$BLK{'Please_wait'}...</h2>
<div class="inline"><input type="submit" name="go" value="click here if page doesn't load..." class="button_green button_mini mt20"></div>
</div>
<input type="hidden" id="words" value="$CROSSWORDS">
<input type="hidden" name="output_web_cache_images" value="$IMAGES">
<input type="hidden" name="output_paper" value="1">
<input type="hidden" id="output_web_crosswords_code_id" name="output_web_crosswords_code" value="">
<script>generate_crosswords();</script>
~;
$AUTO_SUBMIT = qq~<script>onojs_submit();</script>~;

}

}

$WEB .= ONO::FW::Apps::Core->input_vars(\%vars);

$WEB .= $AUTO_SUBMIT;

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




}


# if ($vars{'output_paper'} && $vars{'output_web_crosswords_code'}) {
#
# if (ONO::FW::Apps::Core->print_corrections("$BASE/pdf/pdf-$pdfkey-corr.pdf","",$format,$vars_ref)) {
#
# ONO::FW::Apps::Core->headers($vars_ref,$format,"c");
# ONO::FW::Apps::PDF->title($BLK{'Corrections'},$PDF_OPTS,$vars{'app_input_print_options_code'},$format);
## ONO::Lib::PDF::ToolBox->canvas_test($canvas);
#
#
# }
#
# }
#
# }

if ($vars{'output_paper'} && $vars{'output_web_crosswords_code'}) {

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

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


}

}

$WEB .= ONO::FW::Apps::Core->vardump($vars_ref);

$WEB = ONO::FW::Edu::Apps::ToolBox->apps_gate($WEB,$vars_ref);

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

} else {

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

if (!$vars{'app_input_number_of_questions'}) {
$vars{'app_input_number_of_questions'} = 20;
if (ONO::IO->device eq "phone") {
$vars{'app_input_number_of_questions'} = 10;
}
}

my (
$default_ref,$default_lessons,$all_lessons,$custom_lessons,$LU,
) = ONO::FW::Apps::Core::Lang->lang_default_setup_config(\%vars);
my @default = @$default_ref;

$vars{'software_base'} = $BASE;

if (!$vars{'ouput_web'} && !$vars{'ouput_paper'}) {
$vars{'app_input_display_images_large'} = 1;
}

my $CONF .= ONO::FW::Apps::ToolBox->conf_input("lang", $BLK_ref,\%vars,"ips","$default[0];en:de:fr$LU");
$CONF .= ONO::FW::Apps::ToolBox->conf_input("spacer", $BLK_ref,\%vars);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("selections", $BLK_ref,\%vars,"Nl",$BLK{'lists'},$default_lessons,$all_lessons,"$BLK{'Add_a_list'}::$custom_lessons");
$CONF .= ONO::FW::Apps::ToolBox->conf_input("difficulty", $BLK_ref,\%vars,"i",5,3);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("spacer", $BLK_ref,\%vars);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("check", $BLK_ref,\%vars,"Sd","","display_images",1,"$txt[0] ($BLK{'required'})");
$CONF .= ONO::FW::Apps::ToolBox->conf_input("check", $BLK_ref,\%vars,"S","","display_images_large",$vars{'app_input_display_images_large'},$txt[1]);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("check", $BLK_ref,\%vars,"M","","display_images_words",$vars{'app_input_display_images_words'},$txt[2]);
$CONF .= ONO::FW::Apps::ToolBox->conf_input("spacer", $BLK_ref,\%vars);


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

if (!$vars{'exercise'}) {
$WEB .= ONO::FW::Apps::Core->infopics(
"sheet:200:160:70:15:crosswords_sheet_1.jpg",
"sheet:200:20:100:-10:crosswords_sheet_2.jpg",
);
$WEB .= ONO::FW::Apps::Core->info_display(
ONO::FW::Apps::Core->info("info_indiv_diff", $vars{'app_lang'}),
);
}

$WEB .= ONO::FW::Apps::Core->vardump($vars_ref);

$WEB = ONO::FW::Edu::Apps::ToolBox->apps_gate($WEB,$vars_ref);

}



my ($status,$WEB) = ONO::Lib::Parser->parse($WEB,$vars_ref);

my $VARIATION = ONO::FW::Edu::Apps::Variation->variation();
if ($community eq "school") {
$WEB = ONO::Lib::Encoding::HTML->encode($WEB);
}

return $WEB;

}

sub print_box {

my (
$self,
$canvas,
$letter,
$pos_x,
$pos_y,
$size,
$images_ref,
$switches,
$username,
$community,
) = @_;

# -h hide letter

if ($letter ne "-") {

my %images = %$images_ref;

my $Letter = ONO::Lib::Basic->umlaut_make_uppercase($letter);

if ($letter =~ /[A-Z]/) {

my $IMG_URL = ONO::FW::Apps::Core::Lang->lang_image_url_generator($images{$letter},$username,$community);

ONO::Lib::PDF::Draw->image($canvas,$pos_x,$pos_y,$size,$size,$IMG_URL,1,2);
ONO::Lib::PDF::Draw->circle($canvas,$pos_x+1,$pos_y+1,2,1,"0:150:50:50");
ONO::Lib::PDF::Draw->font("HB",8);
ONO::Lib::PDF::Draw->color(200,200,200);
ONO::Lib::PDF::Draw->text($canvas,$pos_x+1,$pos_y+2,$Letter,"c");
ONO::Lib::PDF::Draw->font("H",12);
ONO::Lib::PDF::Draw->color();

} else {

ONO::Lib::PDF::Draw->square($canvas,$pos_x,$pos_y,$size,1,"","",2);
if ($switches !~ /h/) {
ONO::Lib::PDF::Draw->text($canvas,$pos_x+$size/2,$pos_y+$size*0.6,$Letter,"c");
}

}
}

}

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

1;

__END__