
| Current Path : /var/www/web-klick.de/dsh/10_customer2017/1204__intel/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : /var/www/web-klick.de/dsh/10_customer2017/1204__intel/ProgressBar.pm |
package OptiCm::Engine::Model::Progress::Bar;
#package ProgressBar;
use strict;
use OptiCm::Notifications qw(
progressbar_start
progressbar_step
progressbar_finish
);
use Data::Dumper;
# This module provides an implementatiuon of Progress Bars.
# A Progress Bar consists of:
#
# a) an effort still done
# b) the progress in percent
# c) the plan of work still to be done
#
# We distinguish between atomar and compoung tasks.
#
# Atomar tasks: Where $self->{'PLAN'} is simply a number which
# shows the weight of the task.
#
# Compound tasks: Where $self->{'PLAN'} is a list of subtasks.
our $SLOW_DOWN_FACTOR = 0.9;
#************************************************************************
# Takes a list of weights, constructs tasks of them and appends
# them at the end of the current plan.
#
# If used as a class method, the contructor of the root task.
sub new {
my $self = shift;
my $class = ref($self) || $self;
my @pars = @_;
@pars = (0) if (!@pars);
my $o; my $obj;
$self->{'PLAN'} = [] if (ref($self) and (!(ref($self->{'PLAN'}))));
foreach $o (@pars) {
$obj = {};
$obj->{'PARENT'} = $self;
$obj->{'STEPS_DONE'} = 1;
$obj->{'PLAN'} = $o;
bless($obj,$class);
if (ref($self)) {
$obj->{'GRAFIK'} = $self->{'GRAFIK'};
push(@{$self->{'PLAN'}},$obj);
}
}
return($obj);
}
#******************************************************************************
# Changes the deepest first subtask (this is an atomar task).
#
# All parameters except the first will define new subtasks
# with the given weight.
#
# If the first parameter $weight is < 0, then that
# subtask weights are absolute, if it is zero, all
# weights are normed by the weigth of the originary
# atomar subtask, if $weight is > 0, all weights
# are normed on that value.
sub subtask {
my $self = shift;
my $weight = shift;
my @pars = @_;
my $first_subtask = $self;
if (ref($first_subtask->{'PLAN'})) {
if (!@{$self->{'PLAN'}}) {
$self->new();
}
return($first_subtask->{'PLAN'}->[0]->subtask($weight,@pars));
}
if ($weight == 0) { # take the gross weight from the originally task
$weight = $first_subtask->{'PLAN'};
}
if ($weight > 0) { # sovereign gross weight
my $sum = 0;
map { $sum = $sum + $_ } @pars;
map { $_ = $_ * $weight / $sum } @pars;
} # otherwise the weights of the subtasks are absolute
$first_subtask->new(@pars);
return($first_subtask);
}
#******************************************************************************
# Declares all steps BEFORE as been done and adds that
# efforts to the done work
sub jump {
my $self = shift;
my $o;
$self->{'DONE1'} = shift;
if (ref($self->{'PLAN'})) { # if this is not an atomar plan
if (@{$self->{'PLAN'}}) { # if the list of subtask is not empty
while (@{$self->{'PLAN'}}) { # stepping through all the subtasks
$o = $self->{'PLAN'}->[0];
last if (exists $o->{'DONE1'}); # if there is done work
shift(@{$self->{'PLAN'}});
$self->{'STEPS_DONE'} = $self->{'STEPS_DONE'} + 1;
$self->{'DONE1'} = $self->{'DONE1'} + $o->todo();
}
if ($self->{'PROGRESS'} < 1) { # if there is work to de done
$self->{'DONE1'} = $self->{'DONE1'} + $o->{'DONE1'}; # Computation of done work
$self->{'PROGRESS'} = $self->{'PROGRESS'} + $self->{'DONE1'} /
($self->{'DONE1'} + $self->todo) * ( 1 - $self->{'PROGRESS'} );
$self->{'DONE'} = $self->{'DONE'} + $self->{'DONE1'};
}
}
}
$self->{'PARENT'}->jump() if (ref($self->{'PARENT'}));
delete ($self->{'DONE1'});
}
#***************************************************************
# The remaining todo effort for the task
sub todo {
my $self = shift;
return($self->{'PLAN'}) if (!(ref($self->{'PLAN'})));
my $o; my $erg = 0;
foreach $o (@{$self->{'PLAN'}}) {
$erg = $erg + $o->todo();
}
return($erg);
}
#*********************************************************************************
# Steps to the next sub-task. If that does not exist,
# adds a sub-task with weight $SLOW_DOWN_FACTOR * $self->todo() and steps to it
#
# The bar does not jump reverse if 0 <= $SLOW_DOWN_FACTOR < 1.
sub step {
my $self = shift;
my $laststep = shift || 1;
if ( ref($self->{'PLAN'}) ) {
if ($#{$self->{'PLAN'}} == 0 or $laststep < 0) {
# return(undef) if ($self->{'PLAN'}->[0]->todo() == 0);
# return(undef) if ($self->{'RUNNING'} == 2);
$self->new( $SLOW_DOWN_FACTOR * $self->todo() );
# $self->{'RUNNING'} = 2;
}
if ($#{$self->{'PLAN'}} > 0) {
return( $self->{'PLAN'}->[$laststep]->jump() );
}
}
return( $self->jump() );
}
#*****************************************************************
# Prepares the data structure that has to be sent the
# notifications via printbar_cli resp. printbar_gui.
sub printbar2 {
my $self = shift;
my $bar_elements = shift || [];
my $bar_elements1; my $o;
my $todo = $self->todo();
my $stepsdone = $self->steps_done();
my $stepsplanned = $self->steps_planned();
unshift(@$bar_elements,[$self->done(),$todo,$self->{'REMARK'},
$stepsdone,$stepsplanned,
$self->{'PLAN'}->[0]->{'REMARK'},$self->{'NAME'}]);
return([]) if (!(ref($self->{'PARENT'})));
if ($self->{'SHOWPROGRESS'}) {
my $filter = "(" . $self->{'SHOWPROGRESS'} . ")";
$filter =~ s/\,/\|/gs;
$filter =~ s/\(\(/\(/gs;
$filter =~ s/\)\)/\)/gs;
$bar_elements1 = [];
while (@$bar_elements) { # Collects the information until the
$o = shift(@$bar_elements); # filter expression matches
push(@$bar_elements1,$o);
last if ($o->[6] =~ /$filter/);
}
return($bar_elements1);
}
return($self->{'PARENT'}->printbar2($bar_elements));
}
#***********************************************************
sub printbar_cli {
my $self = shift;
my $bar_elements = $self->printbar2();
return($self->printbar_gui) if ($self->{'GRAFIK'});
my $o; my $done; my $todo; my $remark; my $steps_done; my $steps_planned;
my $gross; my $steps_gross; my $quotient; my $bar; my $name;
my $text = "";
foreach $bar (@$bar_elements) {
$done = $bar->[0];
$todo = $bar->[1];
$gross = $done + $todo;
$name = $bar->[2];
$steps_done = $bar->[3];
$steps_planned = $bar->[4];
$steps_gross = $steps_done + $steps_planned;
$remark = $bar->[5];
$quotient = 0;
if ($gross != 0) { $quotient = $done/$gross; }
$text = $text . substr($remark." "x20,0,20) . " [" .
("=" x int( 30 * $quotient )) . (" " x (30 - int( 30 * $quotient))) .
"]" . sprintf("%6.1f",100 * $quotient) .
substr(" (" . $steps_done . "/" . $steps_gross . ") "." "x13,0,13)
. $name . "\n";
}
return($text);
}
#*****************************************************************
sub printbar_gui {
my $self = shift;
my $bar_elements = shift || $self->printbar2();
if (ref($self->{'PARENT'})) {
return($self->{'PARENT'}->printbar_gui($bar_elements));
}
if ($self->{'BAR_ON'} and !@$bar_elements) {
$self->{'BAR_ON'} = 0;
progressbar_finish();
}
elsif (!($self->{'BAR_ON'}) and @$bar_elements) {
$self->{'BAR_ON'} = 1;
progressbar_start($bar_elements);
}
elsif ($self->{'BAR_ON'}) {
progressbar_step($bar_elements);
}
}
#****************************************************************
sub remark { my $self = shift; $self->{'REMARK'} = shift || $self->{'REMARK'}; return($self); }
sub name { my $self = shift; $self->{'NAME'} = shift || $self->{'NAME'}; return($self); }
sub showprogress { my $self = shift; $self->{'SHOWPROGRESS'} = shift || $self->{'SHOWPROGRESS'}; return($self); }
sub done { my $self = shift; return($self->{'DONE'}); }
sub steps_done { my $self = shift; return($self->{'STEPS_DONE'}); }
sub steps_planned { my $self = shift; return($#{$self->{'PLAN'}}); }
sub start { 1; }
#**************************************************************************
# finish is only a startStep on the level above
sub finish {
my $self = shift;
$self->startStep("Finished.",-1);
sleep 3;
if (ref($self->{'PARENT'})) {
$self->{'PARENT'}->startStep();
}
}
#***************************************************************************
# Steps to the next subtask in $self->{'PLAN'}
sub startStep {
my $self = shift;
my $text = shift;
my $laststep = shift;
if ($self->{'RUNNING'}) {
$self->step($laststep);
$self->{'PLAN'}->[0]->remark($text);
} else { # at the first startStep no real step is performed, only the remark is printed
$self->{'PLAN'}->[0]->remark($text); # so that we only need startStep an do not
$self->printbar_cli(); # have to distinguish between start and startStep
$self->{'RUNNING'} = 1;
}
$self->printbar_cli();
}
#**************************************************************
#**************************************************************
# Constructs a new subtask as a child of the deepest first subtask
sub newBar {
my $self = shift;
my @args = @_;
unshift (@args,'taskLabel') if (@args % 2);
my $pars = { @args };
$pars->{'taskName'} = $pars->{'taskName'} || "newtask"; #
$pars->{'plannedStepCount'} = $pars->{'plannedStepCount'} || 1; # the planned steps
if (!(ref($pars->{'plannedStepCount'}))) { # if it is an arry, then take the weights of that array
$pars->{'plannedStepCount'} = [ (1) x $pars->{'plannedStepCount'} ]; # otherwise construct a series
} # of subtasks of weight 1
if (ref($pars->{'showProgress'})) {
$pars->{'showProgress'} = join(",",@{$pars->{'showProgress'}});
}
my $subtask = $self->subtask( $pars->{'taskWeight'} , @{$pars->{'plannedStepCount'}} );
$subtask->remark( $pars->{'taskLabel'} );
$subtask->showprogress( $pars->{'showProgress'} );
$subtask->name( $pars->{'taskName'} );
return($subtask);
}
#*****************************************************************
# we do not need it .....
sub planSubTask {
my $self = shift;
my $pars = { @_ };
my $weight = $pars->{'taskWeight'} || 1;
my $task = $self->new($weight);
if ($pars->{'taskName'}) {
if (!($pars->{'taskLabel'})) { $pars->{'taskLabel'} = $pars->{'taskName'} }
# $taskList->{ $pars->{'taskName'} } = $task;
}
if ($pars->{'taskLabel'}) {
$task->remark($pars->{'taskLabel'});
}
return($task);
}
#***************************************************************************
sub increasePlannedStepCount { 1; }
1;