ONO::FW::Edu::Apps::Modules::Dictionary

package ONO::FW::Edu::Apps::Modules::Dictionary;
################################################################################
# COPYRIGHT / LICENSE #
################################################################################
#
# This file is part of the ONO Software Project.
#
# Copyright (C) 2022-2026 Jos Kirps and The Joopita Project [ASBL]
# Copyright (C) 2011-2022 Jos Kirps and Joopita Research ASBL
# Copyright (C) 2006-2011 Jos Kirps and The Joopita Project
# Copyright (C) 2001-2006 Jos Kirps and The WobbleWolf Project
#
# This file, as well as many other parts of the ONO Software Project or
# related elements, are FREE SOFTWARE available under the ARTISTIC LICENSE 2.0.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# For the full license, see /ono/osr/license/LICENSE.txt, or write to
# jos_AT_kirps_DOT_com or contact_AT_joopita_DOT_com.
#
################################################################################
# END OF COPYRIGHT / LICENSE, HERE COMES THE CODE ... #
################################################################################

#: This module is a front end application module wrapper that has been
#: created for the Morzino Project (morzino.com) and that has been released
#: as Open Source software.
#:
#: Note that this is NOT a self-contained application, it is only a wrapper
#: that makes heavy use of the ONO Perl Framework application engine.

use strict;

use ONO::Lib::Basic;

use Encode;

use ONO::IO;

use ONO::ToolBox::Auth;
use ONO::Lib::Lang::LangKitEdu;

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

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

use ONO::Lib::UI::Form;
use ONO::FW::User::Init;

sub learn {

my (
$self,
$option,
$vars_ref,
$HTTP,
$BASE,
) = @_;

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;

$vars_ref = ONO::ToolBox::Auth->auth($db,$community,$vars_ref);
%vars = %$vars_ref;

my $WEB;

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

###################################################################
# MAIN SCREEN
###################################################################

if (!$vars{'action'} || $vars{'action'} eq "search") {

my $CLEAR;

if ($vars{'action'} eq "search" && $vars{'query'}) {
my $applang;
if ($vars{'app_lang'}) {
$applang = "?app_lang=$vars{'app_lang'}";
}
$CLEAR = qq~<td><a href="${action_url}$applang" class="button_yellow">$BLK{'clear'}</a></td>~;
}

my $SEARCH = ONO::Lib::UI::Form->search("query",$vars{'query'},$BLK{'search'},400,"green");

$WEB .= qq~<$form>
<input type="hidden" name="action" value="search">
<div class="p10 auto" style="width:600px">
<div class="box_fabric_white_light">
<table class="default_table auto">
<tr>
<td>$SEARCH</td>
$CLEAR
</tr>
</table>
</div>
</div>
</form>
~;

my ($RES,$total) = &core("",0,"$year$mon$mday",$action_url,\%vars);

$WEB .= $RES;

# if no results...

if ($total < 1) {

my $CLOUD = ONO::IO->load("ono-data/school/vocs/cloud.txt");
$CLOUD =~ s~app_lang=(.*?)\&~app_lang=$vars{'app_lang'}\&~g;

if ($ENV{'SCRIPT_NAME'} =~ m~/cgi-bin/local/perl/school/apps/dictionary.pl~) {
$CLOUD =~ s~/cgi-bin/local/perl/school/index_search.pl~/cgi-bin/local/perl/school/apps/dictionary.pl~g;
} else {
$CLOUD =~ s~/cgi-bin/local/perl/school/apps/dictionary.pl~/cgi-bin/local/perl/school/index_search.pl~g;
}

$WEB .= qq~<div class="center auto w90" style="line-height:333%;margin-top:10px">$CLOUD</div>~;

}

}

return $WEB;

}

sub core {

my (
$self,
$total,
$time,
$action_url,
$vars_ref,
) = @_;

my %vars = %$vars_ref;

my $WEB;

if ($action_url !~ /\?/) {
$action_url .= "?";
}

if ($vars{'action'} eq "pxquery") {

$vars{'action'} = "search";
$vars{'query'} = $vars{'pxquery'};

}

if ($vars{'action'} eq "search") {

if (!ONO::IO->exists("ono-data/school/vocs/db_update/$time.txt") || ONO::IO->devstation) {

# update the search database

ONO::IO->mkdir("ono-data/school/vocs/db_update");
ONO::IO->store("ono-data/school/vocs/db_update/$time.txt","updated!");

my @vocs;

for (my $s=3; $s < 7; $s++) {
for (my $l=1; $l < 13; $l++) {

my $l2 = $l;
if ($l < 10) {
$l2 = "0$l";
}

@vocs = (@vocs,ONO::IO->list("ono-data/school/vocs/lessons_$s/basic/$l2.txt"));
@vocs = (@vocs,ONO::IO->list("ono-data/school/vocs/lessons_$s/ext/$l2.txt"));

}
}

my (%word_de,%word_en);
foreach my $voc (@vocs) {
$voc =~ s~\n~~;
my @voc_parts = split(/=/,$voc);
$word_de{$voc_parts[0]} = $voc_parts[1];
$word_en{$voc_parts[0]} = $voc_parts[2];
}

my ($DATA,%freq);

foreach my $key (keys %word_de) {

my $LINE = ONO::Lib::Basic->remove_bad_spaces("$key=$word_de{$key}=$word_en{$key}");
$LINE =~ s~ =~=~g;
$LINE =~ s~= ~=~g;
if ($LINE =~ m/[A-Za-z]/) {
$DATA .= "$LINE\n";
}

# let's build a frequency list of all words...

my @parts = split(/ /,"$key $word_de{$key} $word_en{$key}");
foreach my $part (@parts) {
$part =~ s~^l\'~~;
if (length $part > 3 && $part !~ /(\.)/) {
$freq{$part}++;
}
}

}

my ($FREQ,$count,@cloudwords);
foreach my $key (sort { $freq{$b} <=> $freq{$a} } keys %freq) {
$count++;
$FREQ .= qq~$key\n~;
if ($count < 50) {
@cloudwords = (@cloudwords,$key);
}
}

my $CLOUD;
foreach my $key (sort @cloudwords) {

my $size = 10+int($freq{$key}/2);

my $color = "666666";
if ($size < 50) {
$color = "999999";
}
if ($size < 40) {
$color = "aaaaaa";
}
if ($size < 30) {
$color = "bbbbbb";
}
if ($size < 20) {
$color = "cccccc";
}
if ($size < 10) {
$color = "dddddd";
}

$CLOUD .= qq~<span style="font-size:${size}px;padding:10px">
<a href="${action_url}&action=search&option=search&query=$key" style="color:#$color">$key</a>
</span> ~;
}

ONO::IO->store("ono-data/school/vocs/db.txt",$DATA);
ONO::IO->store("ono-data/school/vocs/freq.txt",$FREQ);
ONO::IO->store("ono-data/school/vocs/cloud.txt",$CLOUD);

}

# start searching

if (length $vars{'query'} > 2) {

my $query_test = lc $vars{'query'};
$query_test =~ s~[^a-z\ ]~~g;

# vokabelen (alles)

my @vocs = ONO::IO->quicklist("ono-data/school/vocs/db.txt");

my $URL = "${action_url}&action=search&option=search&query=";
if ($action_url eq "/cgi-bin/local/perl/school/index_search.pl") {
$URL = "/search/?query=";
}

my @langs = ('fr','de','en');
my @lang_order = (0,1,2);
if ($vars{'pxlang'} eq "en" || $vars{'lang'} eq "en") {
@lang_order = (2,1,0);
}
if ($vars{'pxlang'} eq "de" || $vars{'lang'} eq "de") {
@lang_order = (1,2,0);
}
if ($vars{'pxlang'} eq "fr" || $vars{'lang'} eq "fr") {
@lang_order = (0,2,1);
}
if ($vars{'pxlang'} eq "lu" || $vars{'lang'} eq "lu") {
@lang_order = (1,0,2);
}

my ($FOUND,@FOUNDS,%used);

foreach my $voc (@vocs) {

my $voc_test = lc $voc;
$voc_test =~ s~[^a-z\=\ ]~~g;

if ($voc_test =~ /$query_test/ && !$used{$voc_test}) {

$used{$voc_test}++;

my @voc_parts = split(/=/,$voc);

my $test0 = $voc_parts[0];
my $test1 = $voc_parts[1];
my $test2 = $voc_parts[2];

$voc_parts[0] =~ s~($vars{'query'})~\[b\]${1}\[\/b\]~gi;
$voc_parts[1] =~ s~($vars{'query'})~\[b\]${1}\[\/b\]~gi;
$voc_parts[2] =~ s~($vars{'query'})~\[b\]${1}\[\/b\]~gi;

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

my @words = split(/ /,$voc_parts[$i]);

foreach my $word (@words) {
if (length $word > 3 && $word !~ /(\<|\.|\,|\=|\'|\(|\))/) {

if ($vars{'pxquery'}) {
$voc_parts[$i] =~ s~$word~<a href="/picture-dictionary/$langs[$i]/-/-/$word/">$word</a>~g;
} else {
$voc_parts[$i] =~ s~$word~<a href="$URL$word">$word</a>~g;
}

}
if (length $word > 3 && $word =~ /^l\'(.*?)$/ && $word !~ /(\(|\))/) {

my $core = $1;

if ($vars{'pxquery'}) {
$voc_parts[$i] =~ s~$word~l\'<a href="/picture-dictionary/$langs[$i]/-/-/$core/">$core</a>~g;
} else {
$voc_parts[$i] =~ s~$word~l\'<a href="$URL$core">$core</a>~g;
}

}
}
}

$total++;

if (

$test0 eq $vars{'query'} || $test1 eq $vars{'query'} ||

$test0 =~ /^(le|la|les) $vars{'query'}$/ || $test1 =~ /^(le|la|les) $vars{'query'}$/ ||
$test0 =~ /^l\'$vars{'query'}$/ || $test1 =~ /^l\'$vars{'query'}$/ ||

$test0 =~ /^(der|die|das) $vars{'query'}$/ || $test1 =~ /^(der|die|das) $vars{'query'}$/ ||

$test0 =~ /^(the) $vars{'query'}$/ || $test1 =~ /^(the) $vars{'query'}$/

) {

my $sort = $voc_parts[$lang_order[0]];
$sort =~ s~[^A-Za-z]~~g;

@FOUNDS = (
@FOUNDS,
qq~<!-- sort:$sort -->
<div class="bg_green inline w100 bb">
<div class="w33 fl w100_720 fn_720"><div class="pad10_2 br bl">$voc_parts[$lang_order[0]]</div></div>
<div class="w33 fl w100_720 fn_720"><div class="pad10_2 br">$voc_parts[$lang_order[1]]</div></div>
<div class="w33 fl w100_720 fn_720"><div class="pad10_2 br">$voc_parts[$lang_order[2]]</div></div>
</div>
~,
);

} else {

my $sort = $voc_parts[$lang_order[0]];
$sort =~ s~[^A-Za-z]~~g;

@FOUNDS = (
@FOUNDS,
qq~<!-- sort:$sort -->
<div class="###BG### inline w100 bb">
<div class="w33 fl w100_720 fn_720"><div class="pad10_2 br bl">$voc_parts[$lang_order[0]]</div></div>
<div class="w33 fl w100_720 fn_720"><div class="pad10_2 br">$voc_parts[$lang_order[1]]</div></div>
<div class="w33 fl w100_720 fn_720"><div class="pad10_2 br">$voc_parts[$lang_order[2]]</div></div>
</div>
~,
);

}
}
}

my $counter;

foreach my $FND (sort @FOUNDS) {

$counter++;
my $BG = "bg_fabric";
if ($counter%2 == 0) {
$BG = "bg_paper";
}

$FND =~ s~###BG###~$BG~;

$FOUND .= $FND;
}

if ($FOUND) {

my @flags = ('fr','de','en');

if ($ENV{'SCRIPT_NAME'} =~ m~/cgi-bin/local/perl/school/apps/~) {
$FOUND = qq~<div style="height:360px;overflow-x:hidden;overflow-x:scroll">$FOUND</div>~;
}

$WEB .= qq~<div class="inline w100">
<div class="inline w100 bb hide720">
<div class="w33 fl w100_720 fn_720">
<div class="shadow ml10 mb5" style="width:24px;height:16px">
<img class="flag" src="/ono/osr/images/flags/countries_large_tld/$flags[$lang_order[0]].jpg" style="width:24px;height:16px" alt="">
</div>
</div>
<div class="w33 fl w100_720 fn_720">
<div class="shadow ml10 mb5" style="width:24px;height:16px">
<img class="flag" src="/ono/osr/images/flags/countries_large_tld/$flags[$lang_order[1]].jpg" style="width:24px;height:16px" alt="">
</div>
</div>
<div class="w33 fl w100_720 fn_720">
<div class="shadow ml10 mb5" style="width:24px;height:16px">
<img class="flag" src="/ono/osr/images/flags/countries_large_tld/$flags[$lang_order[2]].jpg" style="width:24px;height:16px" alt="">
</div>
</div>
</div>
$FOUND
</div>
~;

}

# done

}

}

return ($WEB,$total);

}

###################################################################
# VOC PARTS
###################################################################

sub voc_parts {

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

$voc =~ s~ ~~g;
$voc =~ s~ \^~\^~g;
my @voc_parts = split(/\^/,$voc);

$voc_parts[1] =~ s~m\.~den ~gi;
$voc_parts[1] =~ s~f\.~d'~gi;
$voc_parts[1] =~ s~n\.~d'~gi;
$voc_parts[1] =~ s~p\.~d'~gi;
$voc_parts[1] =~ s~^den (B|C|F|G|J|K|L|M|N|P|Q|R|S|V|W|X)~de $1~gi;
if (length $vars{'query'} > 3) {
$voc_parts[1] =~ s~($vars{'query'})~<span class="bold">$1</span>~gi;
}

$voc_parts[2] =~ s~m\.~der ~gi;
$voc_parts[2] =~ s~f\.~die ~gi;
$voc_parts[2] =~ s~n\.~das ~gi;
$voc_parts[2] =~ s~p\.~die ~gi;
if (length $vars{'query'} > 3) {
$voc_parts[2] =~ s~($vars{'query'})~<span class="bold">$1</span>~gi;
}

$voc_parts[3] =~ s~m\.~le ~gi;
$voc_parts[3] =~ s~f\.~la ~gi;
$voc_parts[3] =~ s~p\.~les ~gi;
$voc_parts[3] =~ s~^l(a|e) (e|u|i|o|a|h|y)~l'$2~gi;
if (length $vars{'query'} > 3) {
$voc_parts[3] =~ s~($vars{'query'})~<span class="bold">$1</span>~gi;
}

$voc_parts[4] =~ s~m\.~the ~gi;
# $voc_parts[4] =~ s~^a (e|u|i|o|a)~an $1~gi;
if (length $vars{'query'} > 3) {
$voc_parts[4] =~ s~($vars{'query'})~<span class="bold">$1</span>~gi;
}

return ($voc_parts[0],$voc_parts[1],$voc_parts[2],$voc_parts[3],$voc_parts[4]);
}


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

1;

__END__