package ONO::FW::Apps::Core::Stats;
################################################################################
# COPYRIGHT / LICENSE #
################################################################################
#
# This file is part of the ONO Software Project.
#
# Copyright (C) 2000-2025 Jos KIRPS [ www.kirps.com | jos_AT_kirps_DOT_com ]
# and The Joopita Project [ www.joopita.org | contact_AT_joopita_DOT_com ]
#
# This file, as well as 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 ... #
################################################################################
use strict;
###################################################################
#
###################################################################
#: This module offers functions that allow to generate and view
#: ONO app exercise stats.
sub stats_multi_pages {
my (
$self,
$questions,
$stat_correct,
$stat_wrong,
$page,
$pages,
$questions_per_page,
) = @_;
#: Multi-page statistics.
if (!$questions_per_page) {
$questions_per_page = 20;
}
# don't change the order of the following two lines !!!
my $stat_todo_total = $questions-$stat_correct-$stat_wrong;
if ($page && $pages) {
$stat_correct = $stat_correct+(($page-1)*$questions_per_page);
$stat_todo_total = $stat_todo_total-(($page-1)*$questions_per_page);
}
return ($stat_correct,$stat_todo_total);
}
sub stats_replace {
#: Replace placeholders by actual data.
my @data = @_;
for (my $i = 2; $i < 10; $i++) {
if ($data[$i] < 1) {
$data[$i] = 0;
}
}
if ($data[8]) {
# completed:
$data[2]++,
$data[4] = 0;
$data[6] = $data[7];
}
$data[1] =~ s~###CORRECT###~$data[2]~;
$data[1] =~ s~###WRONG###~$data[3]~;
$data[1] =~ s~###TODO###~$data[4]~;
$data[1] =~ s~###MISTAKES###~$data[5]~;
if ($data[7]) {
$data[1] =~ s~###PAGE###~$data[6] / $data[7]~;
} else {
$data[1] =~ s~###PAGE###~$data[6]~;
}
$data[1] =~ s~###HINTS###~$data[9]~;
return $data[1];
}
sub stats {
my (
$self,
$MORE,
$BLK_ref,
$switches,
) = @_;
my %BLK = %$BLK_ref;
#: Generate statistics.
#:
#: Switches:
#:
#: -a absolute position
#: -B buttom margin 10px
#: -c center
#: -C 'completed' instead of 'correct'
#: -e use "total errors" instead of "not correct"
#: -h hint box
#: -H hint box V2
#: -m mistakes
#: -M mistakes, red
#: -L left margin 10px
#: -p pages (also see -s and -x)
#: -P phone -> disappear if screen smaller than 800 px
#: -q sQuare display (2+2)
#: -R right margin 10px
#: -s use "screen" instead of "page"
#: -S submit button
#: -t top margin 10px
#: -T hide 'todo' tab
#: -v vertical (also see 'q' ass an alternative)
#: -V vertical limit to 150px (also see 'q' ass an alternative)
#: -W hide 'wrong' tab
#: -x use "exercise" instead of "page"
#: -z set correct to zero by default, not replacement string
my ($DIV_CLASS,$DIV_STYLE,$STYLE,$HINT,$MIST,$PAGE,$WRONG,$TODO);
my $TD = qq~<td class="nowrap bold small">~;
my $WIDE = "wide";
my $SEP = qq~<td></td>~;
my $SEP2;
if ($switches =~ /v/) {
$SEP = qq~</tr><tr>~;
}
if ($switches =~ /V/) {
$DIV_STYLE = "width:150px;"
}
if ($switches =~ /q/) {
$SEP2 = qq~</tr><tr>~;
}
if ($switches =~ /a/) {
$DIV_CLASS .= "abs ";
}
if ($switches =~ /P/) {
$DIV_CLASS .= "hide800 ";
}
if ($switches =~ /c/) {
$STYLE .= qq~margin:auto;~;
$WIDE = "default";
}
if ($switches =~ /C/) {
$BLK{'correct'} = $BLK{'completed'};
}
if ($switches =~ /(m|M)/) {
my $color = "yellow";
if ($switches =~ /M/) {
$color = "red";
}
$MIST = qq~$SEP$TD<div class="box_$color bo_dark radius10 pad10_2 center"><span id="output_web_total_mistakes">###MISTAKES###</span><span class="hide720"> $BLK{'mistakes'}</span></div></td>~;
}
if ($switches =~ /p/) {
if ($switches =~ /s/) {
$BLK{'page'} = $BLK{'screen'};
}
if ($switches =~ /x/) {
$BLK{'page'} = $BLK{'exercise'};
}
$PAGE = qq~$TD<div class="box_fabric bo_dark radius10 pad10_2 center">$BLK{'page'}<span class="hide720"> ###PAGE###</span></div></td>$SEP~;
}
# we can't use margin here, need to use padding in order to avoid
# iframe scrollbars
if ($switches =~ /t/) {
$DIV_STYLE .= qq~padding-top:10px;~;
}
if ($switches =~ /B/) {
$DIV_STYLE .= qq~padding-bottom:10px;~;
}
if ($switches =~ /L/) {
$DIV_STYLE .= qq~padding-left:10px;~;
}
if ($switches =~ /R/) {
$DIV_STYLE .= qq~padding-right:10px;~;
}
if ($switches =~ /h/) {
$HINT = qq~$SEP$TD<div class="box_yellow bo_dark radius10 pad10_2 center"><span id="total_hints">###HINTS###</span><span class="hide720"> $BLK{'hints'}</span></div></td>~;
}
if ($switches =~ /H/) {
$HINT = qq~$SEP$TD<div class="box_yellow bo_dark radius10 pad10_2 center"><span id="output_web_total_hints">###HINTS###</span><span class="hide720"> $BLK{'hints'}</span></div></td>~;
}
if ($switches !~ /T/) {
$TODO = qq~$TD<div class="box_fabric bo_dark radius10 pad10_2 center"><span id="total_todo">###TODO###</span><span class="hide720"> $BLK{'not_done'}</span></div></td>~;
}
if ($switches !~ /W/) {
if ($switches =~ /e/) {
$BLK{'wrong'} = $BLK{'total_errors'};
}
$WRONG = qq~$TD<div class="box_red bo_dark radius10 pad10_2 center"><span id="output_web_total_wrong">###WRONG###</span><span class="hide720"> $BLK{'wrong'}</span></div></td>$SEP~;
}
if ($MORE) {
$MORE = qq~$SEP<td class="small" style="line-height:100%">$MORE</td>~;
}
if ($switches =~ /S/) {
my $SUBMIT = $BLK{'do_correct'};
$MORE = qq~$SEP<td class="small" style="line-height:100%"><input type="submit" name="stats_submit" value="$SUBMIT" class="button_green"></td>~;
}
my $CORRECT = "###CORRECT###";
if ($switches =~ /z/) {
$CORRECT = 0;
}
return qq~<div class="$DIV_CLASS" style="$DIV_STYLE">
<table class="${WIDE}_table" style="$STYLE">
<tr>
$PAGE
$TD<div class="box_green bo_dark radius10 pad10_2 center"><span id="total_correct">$CORRECT</span><span class="hide720"> $BLK{'correct'}</span></div></td>
$MIST
$SEP
$WRONG
$SEP2
$TODO
$HINT
$MORE
</tr>
</table>
</div>
~;
}
###################################################################
# THAT'S IT :-D
###################################################################
1;
__END__