# HG changeset patch # User devi # Date 1135724460 -7200 # Node ID 43aeb3036aaa0a3f35edad44a800683cc8028db1 # Parent d3fcff5e375752452dbd32d18fce39275c4b6600 l3-frontend: Наведение порядка в коде. Пока что, он ещё достаточно сырой и некрасивый, но это всё же лучше, чем то, что было раньше. Добавлено: * команды, набранные с ошибками показываются зачёркнутым текстом * в статистике подсвечиваются известные/неизвестные команды, как раньше по тексту * в названиях программ/скриптов пути, содержащие /etc, не отрезаются l3-agent: Неправильно передавался код завершения. Fixed Код откровенно мерзкий и требует доработок diff -r d3fcff5e3757 -r 43aeb3036aaa l3-agent --- a/l3-agent Thu Dec 22 11:56:06 2005 +0200 +++ b/l3-agent Wed Dec 28 01:01:00 2005 +0200 @@ -814,7 +814,7 @@ print OUT "",$cl->{raw_file},"\n"; print OUT "",$cl->{tty},"\n"; print OUT "",$out_class,"\n"; - print OUT "",$out_class,"\n"; + print OUT "",$cl->{err},"\n"; print OUT ""; printq(\*OUT,,$cl->{"prompt"}); print OUT ""; diff -r d3fcff5e3757 -r 43aeb3036aaa l3-frontend --- a/l3-frontend Thu Dec 22 11:56:06 2005 +0200 +++ b/l3-frontend Wed Dec 28 01:01:00 2005 +0200 @@ -25,18 +25,21 @@ my %mywi_cache_for; # Кэш для экономии обращений к mywi - -sub search_buy; sub make_comment; sub load_command_lines_from_xml; sub load_sessions_from_xml; -sub print_command_lines; sub sort_command_lines; sub process_command_lines; sub init_variables; sub main; sub collapse_list($); +sub print_all; +sub print_command_lines; +sub print_stat; +sub print_header; +sub print_footer; + main(); sub main @@ -51,71 +54,75 @@ load_sessions_from_xml($Config{"backend_datafile"}); sort_command_lines; process_command_lines; - print_command_lines($Config{"output"}); + print_all($Config{"output"}); close_mywi_socket; } +# extract_from_cline -sub search_by -{ - my $sm = shift; - my $topic = shift; - $topic =~ s/ /+/; - - return ""; -} +# In: $what = commands | args +# Out: return ссылка на хэш, содержащий результаты разбора +# команда => позиция -sub extract_from_cline # Разобрать командную строку $_[1] и возвратить хэш, содержащий # номер первого появление команды в строке: # команда => первая позиция +sub extract_from_cline { my $what = $_[0]; my $cline = $_[1]; my @lists = split /\;/, $cline; - my @commands = (); - for my $list (@lists) { - push @commands, split /\|/, $list; + my @command_lines = (); + for my $command_list (@lists) { + push(@command_lines, split(/\|/, $command_list)); } - my %commands; - my %args; + my %position_of_command; + my %position_of_arg; my $i=0; - for my $command (@commands) { - $command =~ s@^\s*\S+/@@; - $command =~ /\s*(\S+)\s*(.*)/; + for my $command_line (@command_lines) { + $command_line =~ s@^\s*@@; + $command_line =~ /\s*(\S+)\s*(.*)/; if ($1 && $1 eq "sudo" ) { - $commands{"$1"}=$i++; - $command =~ s/\s*sudo\s+//; + $position_of_command{"$1"}=$i++; + $command_line =~ s/\s*sudo\s+//; } - $command =~ s@^\s*\S+/@@; - $command =~ /\s*(\S+)\s*(.*)/; - if ($1 && !defined $commands{"$1"}) { - $commands{"$1"}=$i++; + if ($command_line !~ m@^\s*\S*/etc/@) { + $command_line =~ s@^\s*\S+/@@; + } + + $command_line =~ /\s*(\S+)\s*(.*)/; + my $command = $1; + my $args = $2; + if ($command && !defined $position_of_command{"$command"}) { + $position_of_command{"$command"}=$i++; }; - if ($2) { - my $args = $2; + if ($args) { my @args = split (/\s+/, $args); for my $a (@args) { - $args{"$a"}=$i++ - if !defined $args{"$a"}; + $position_of_arg{"$a"}=$i++ + if !defined $position_of_arg{"$a"}; }; - - } } if ($what eq "commands") { - return \%commands; + return \%position_of_command; } else { - return \%args; + return \%position_of_arg; } } + + + +# +# Подпрограммы для работы с mywi +# + sub open_mywi_socket { $Mywi_Socket = IO::Socket::INET->new( @@ -204,6 +211,9 @@ Процедура load_command_lines_from_xml выполняет загрузку разобранного lab-скрипта из XML-документа в переменную @Command_Lines +# In: $datafile имя файла +# Out: @CommandLines загруженные командные строки + Предупреждение! Процедура не в состоянии обрабатывать XML-документ любой структуры. В действительности файл cache из которого загружаются данные @@ -248,11 +258,12 @@ } +# sort_command_lines +# In: @Command_Lines +# Out: @Command_Lies_Index sub sort_command_lines { - # Sort Command_Lines - # Write Command_Lines to Command_Lines_Index my @index; for (my $i=0;$i<=$#Command_Lines;$i++) { @@ -265,99 +276,87 @@ } +################## +# process_command_lines +# +# Обрабатываются командные строки @Command_Lines +# Для каждой строки определяется: +# class класс +# note комментарий +# +# In: @Command_Lines_Index +# In-Out: @Command_Lines + sub process_command_lines { for my $i (@Command_Lines_Index) { + my $cl = \$Command_Lines[$i]; - my $cl = \$Command_Lines[$i]; - #@{${$cl}->{"new_commands"}} =(); - #@{${$cl}->{"new_files"}} =(); - $$cl->{"class"} = ""; + next if !$cl; - if ($$cl->{"err"}) { - $$cl->{"class"}="wrong"; - $$cl->{"class"}="interrupted" - if ($$cl->{"err"} eq 130); - } + $$cl->{err} ||=0; + + # Класс команды + + $$cl->{"class"} = $$cl->{"err"} eq 130 ? "interrupted" + : $$cl->{"err"} eq 127 ? "mistyped" + : $$cl->{"err"} ? "wrong" + : ""; + if (!$$cl->{"euid"}) { $$cl->{"class"}.="_root"; } - -#tab# my @tab_words=split /\s+/, $$cl->{"output"}; -#tab# my $last_word= $$cl->{"cline"} =~ /(\S*)$/; -#tab# $last_word =~ s@.*/@@; -#tab# my $this_is_tab=1; -#tab# -#tab# if ($last_word && @tab_words >2) { -#tab# for my $tab_words (@tab_words) { -#tab# if ($tab_words !~ /^$last_word/) { -#tab# $this_is_tab=0; -#tab# last; -#tab# } -#tab# } -#tab# } -#tab# $$cl->{"class"}="tab" if $this_is_tab; - -# if ( !$$cl->{"err"}) { -# # Command does not contain mistakes -# -# my %commands = extract_from_cline("commands", ${$cl}->{"cline"}); -# my %files = extract_from_cline("files", ${$cl}->{"cline"}); -# -# # Searching for new commands only -# for my $command (keys %commands) { -# if (!defined $Commands_Stat{$command}) { -# push @{$$cl->{new_commands}}, $command; -# } -# $Commands_Stat{$command}++; -# } -# -# for my $file (keys %files) { -# if (!defined $Files_Stat{$file}) { -# push @{$$cl->{new_files}}, $file; -# } -# $Files_Stat{$file}++; -# } -# } + +#Обработка пометок +# Если несколько пометок (notes) идут подряд, +# они все объединяются if ($$cl->{cline}=~ m@cat[^#]*#([\^=v])\s*(.*)@) { - if ($1 eq "=") { + + my $note_operator = $1; + my $note_title = $2; + + if ($note_operator eq "=") { $$cl->{"class"} = "note"; $$cl->{"note"} = $$cl->{"output"}; $$cl->{"note_title"} = $2; } else { my $j = $i; - if ($1 eq "^") { + if ($note_operator eq "^") { $j--; $j-- while ($j >=0 && (!$Command_Lines[$j] || $Command_Lines[$j]->{tty} ne $$cl->{tty})); } - elsif ($1 eq "v") { + elsif ($note_operator eq "v") { $j++; $j++ while ($j <= @Command_Lines && (!$Command_Lines[$j] || $Command_Lines[$j]->{tty} ne $$cl->{tty})); } - $Command_Lines[$j]->{note_title}="$2"; - $Command_Lines[$j]->{note}=$$cl->{output}; + $Command_Lines[$j]->{note_title}=$note_title; + $Command_Lines[$j]->{note}.=$$cl->{output}; $$cl=0; } } elsif ($$cl->{cline}=~ /#([\^=v])(.*)/) { - if ($1 eq "=") { + + my $note_operator = $1; + my $note_text = $2; + + if ($note_operator eq "=") { $$cl->{"class"} = "note"; - $$cl->{"note"} = $2; + $$cl->{"note"} = $note_text; } else { my $j=$i; - if ($1 eq "^") { + if ($note_operator eq "^") { $j--; $j-- while ($j >=0 && (!$Command_Lines[$j] || $Command_Lines[$j]->{tty} ne $$cl->{tty})); } - elsif ($1 eq "v") { + elsif ($note_operator eq "v") { $j++; $j++ while ($j <= @Command_Lines && $Command_Lines[$j]->{tty} ne $$cl->{tty} || !$Command_Lines[$j]); } - $Command_Lines[$j]->{note}.="$2\n"; + $Command_Lines[$j]->{note}.="$note_text\n"; $$cl=0; } } @@ -375,64 +374,74 @@ sub print_command_lines { - my $output_filename=$_[0]; - my $course_name = $Config{"course-name"}; - my $course_code = $Config{"course-code"}; - my $course_date = $Config{"course-date"}; - my $course_center = $Config{"course-center"}; - my $course_trainer = $Config{"course-trainer"}; - my $course_student = $Config{"course-student"}; - - - # Результат выполнения процедуры равен - # join("", @Result{header,body,stat,help,about,footer}) - my %Result; - my @toc; # Хранит оглавление + my @toc; # Оглавление my $note_number=0; - $Result{"body"} = "\n"; + my $result = q(); + my $this_day_resut = q(); my $cl; my $last_tty=""; - my $last_day=""; + my $last_day=q(); + my $last_wday=q(); my $in_range=0; my $current_command=0; + my %filter; + + if ($Config{filter}) { + # Инициализация фильтра + my %filter; + for (split /&/,$Config{filter}) { + my ($var, $val) = split /=/; + $filter{$var} = $val || ""; + } + } + + $Stat{LastCommand} ||= 0; + $Stat{TotalCommands} ||= 0; + $Stat{ErrorCommands} ||= 0; + $Stat{MistypedCommands} ||= 0; + COMMAND_LINE: for my $k (@Command_Lines_Index) { my $cl=$Command_Lines[$Command_Lines_Index[$current_command++]]; - next unless $cl; +# Пропускаем команды, с одинаковым временем +# Это не совсем правильно. +# Возможно, что это команды, набираемые с помощью +# или запомненные с помощью - if ($Config{filter}) { - # Инициализация фильтра - my %filter; - for (split /&/,$Config{filter}) { - my ($var, $val) = split /=/; - $filter{$var} = $val || ""; - } + next if $Stat{LastCommand} == $cl->{time}; - for my $filter_key (keys %filter) { - next COMMAND_LINE if - defined($cl->{local_session_id}) - && defined($Sessions{$cl->{local_session_id}}->{$filter_key}) - && $Sessions{$cl->{local_session_id}}->{$filter_key} ne $filter{$filter_key}; - #print $filter_key,"\n"; - } +# Набираем статистику +# Хэш %Stat - #if ($filter{user}) { - # next COMMAND_LINE unless $Sessions{$cl->{local_session_id}}->{user} eq $filter{user}; - #} + $Stat{FirstCommand} = $cl->{time} unless $Stat{FirstCommand}; + if ($cl->{time} - $Stat{LastCommand} < $Config{stat_inactivity_interval}) { + $Stat{TotalTime} += $cl->{time} - $Stat{LastCommand} + } + $Stat{LastCommand} = $cl->{time}; + $Stat{TotalCommands}++; - #for my $filter_field (keys %filter) { - # next COMMAND_LINE unless $Sessions{$cl->{local_session_id}}->{$filter_field} eq $filter{$filter_field}; - #} +# Пропускаем строки, которые противоречат фильтру +# Если у нас недостаточно информации о том, подходит строка под фильтр или нет, +# мы её выводим + + for my $filter_key (keys %filter) { + next COMMAND_LINE if + defined($cl->{local_session_id}) + && defined($Sessions{$cl->{local_session_id}}->{$filter_key}) + && $Sessions{$cl->{local_session_id}}->{$filter_key} ne $filter{$filter_key}; } +# Пропускаем строки, выходящие за границу "signature", +# при условии, что границы указаны +# Пропускаем неправильные/прерванные/другие команды if ($Config{"from"} && $cl->{"cline"} =~ /$Config{"signature"}\s*$Config{"from"}/) { $in_range=1; next; @@ -441,25 +450,19 @@ $in_range=0; next; } - next if ($Config{"from"} && $Config{"to"} && !$in_range) - || - ($Config{"skip_empty"} =~ /^y/i && $cl->{"cline"} =~ /^\s*$/ ) - || - ($Config{"skip_wrong"} =~ /^y/i && $cl->{"err"} != 0) - || - ($Config{"skip_interrupted"} =~ /^y/i && $cl->{"err"} == 130); + next if ($Config{"from"} && $Config{"to"} && !$in_range) + || ($Config{"skip_empty"} =~ /^y/i && $cl->{"cline"} =~ /^\s*$/ ) + || ($Config{"skip_wrong"} =~ /^y/i && $cl->{"err"} != 0) + || ($Config{"skip_interrupted"} =~ /^y/i && $cl->{"err"} == 130); - #my @new_commands=@{$cl->{"new_commands"}}; - #my @new_files=@{$cl->{"new_files"}}; - if ($cl->{class} eq "note") { my $note = $cl->{note}; $note = join ("\n", map ("

$_

", split (/-\n/, $note))); $note =~ s@(http:[a-zA-Z.0-9/?\_%-]*)@$1@g; $note =~ s@(www\.[a-zA-Z.0-9/?\_%-]*)@$1@g; - $Result{"body"} .= "
"; + $result .= ""; if ($cl->{note_title}) { push @{$toc[@toc]},"".$cl->{note_title}.""; @@ -468,192 +471,343 @@ next; } - my $cl_class="cline"; - my $out_class="output"; - if ($cl->{"class"}) { - $cl_class = $cl->{"class"}."_".$cl_class; - $out_class = $cl->{"class"}."_".$out_class; - } - - my @new_commands; - my @new_files; - @new_commands = split (/\s+/, $cl->{"new_commands"}) if defined $cl->{"new_commands"}; - @new_files = split (/\s+/, $cl->{"new_files"}) if defined $cl->{"new_files"}; my $output=""; - if ($Config{"head_lines"} || $Config{"tail_lines"}) { - # Partialy output - my @lines = split '\n', $cl->{"output"}; - # head - my $mark=1; +# Выводим верхних строк +# и нижних строк, +# если эти параметры существуют + + my @lines = split '\n', $cl->{"output"}; + if (($Config{"head_lines"} || $Config{"tail_lines"}) + && $#lines > $Config{"head_lines"} + $Config{"tail_lines"} ) { + for (my $i=0; $i<= $#lines && $i < $Config{"head_lines"}; $i++) { $output .= $lines[$i]."\n"; } - # tail - my $start=$#lines-$Config{"tail_lines"}+1; - if ($start < 0) { - $start=0; - $mark=0; - } - if ($start < $Config{"head_lines"}) { - $start=$Config{"head_lines"}; - $mark=0; - } - $output .= $Config{"skip_text"}."\n" if $mark; - for ($i=$start; $i<= $#lines; $i++) { + $output .= $Config{"skip_text"}."\n"; + + my $start_line=$#lines-$Config{"tail_lines"}+1; + for ($i=$start_line; $i<= $#lines; $i++) { $output .= $lines[$i]."\n"; } } else { - # Full output $output .= $cl->{"output"}; } - #$output .= "^C\n" if ($cl->{"err"} eq "130"); - # - ## - ## Начинается собственно вывод - ## - # - - # +# +## +## Начинается собственно вывод +## +# my ($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst) = localtime($cl->{time}); - next if $Stat{LastCommand} == $cl->{time}; - $Stat{FirstCommand} = $cl->{time} unless $Stat{FirstCommand}; - $Stat{LastCommand} = 0 unless defined $Stat{LastCommand}; - $Stat{TotalTime} += $cl->{time} - $Stat{LastCommand} - if $cl->{time} - $Stat{LastCommand} < $Config{stat_inactivity_interval}; - $Stat{LastCommand} = $cl->{time}; - $Stat{TotalCommands} = 0 unless $Stat{TotalCommands}; - $Stat{TotalCommands}++; # Добавляем спереди 0 для удобочитаемости - $min = "0".$min if $min =~ /^.$/; + $min = "0".$min if $min =~ /^.$/; $hour = "0".$hour if $hour =~ /^.$/; - $sec = "0".$sec if $sec =~ /^.$/; + $sec = "0".$sec if $sec =~ /^.$/; - $class=$cl->{"out_class"}; - $class =~ s/output$//; + #my @new_commands; + #my @new_files; + #@new_commands = split (/\s+/, $cl->{"new_commands"}) if defined $cl->{"new_commands"}; + #@new_files = split (/\s+/, $cl->{"new_files"}) if defined $cl->{"new_files"}; - $Stat{ErrorCommands}++ - if $class =~ /wrong/; + $class=$cl->{"class"}; + $Stat{ErrorCommands}++ if $class =~ /wrong/; + $Stat{MistypedCommands}++ if $class =~ /mistype/; - $Result{"body"} .= "\n"; - - # DAY CHANGE +# DAY CHANGE if ( $last_day ne $day) { - #$Result{"body"} .= ""; - $Result{"body"} .= ""; + if ($last_day) { + $result .= "

".$Day_Name[$last_wday]."

"; + #$result .= "Новые команды
"; + $result .= "
"; - $Result{"body"} .= "

".$cl->{note_title}."

" if $cl->{note_title}; - $Result{"body"} .= "".$note."

"; + $result .= "

".$cl->{note_title}."

" if $cl->{note_title}; + $result .= "".$note."

День ",$day,"

".$Day_Name[$wday]."

\n"; + $result .= $this_day_result; + $result .= "
"; + } + push @toc, "".$Day_Name[$wday]."\n"; $last_day=$day; + $last_wday=$wday; + $this_day_result = q(); } - # CONSOLE CHANGE + $this_day_result .= "\n"; + + +# CONSOLE CHANGE if ( $last_tty ne $cl->{"tty"}) { - my $host; - #$host = $Sessions{$cl->{local_session_id}}->{user}."@".$Sessions{$cl->{local_session_id}}->{hostname}; - my $body = $cl->{"tty"}; - $body .= " \@$host" if $host; - $Result{"body"} .= "
".$body."
"; + my $tty = $cl->{"tty"}; + $this_day_result .= "" + ."
" + . $tty + ."
" + .""; $last_tty=$cl->{"tty"}; } - # TIME - if ($Config{"show_time"} =~ /^y/i) { - $Result{"body"} .= "
".
-                $hour. ":". $min. ":". $sec.
-                "";
-        } else {
-            $Result{"body"} .= ""
-        }
+# TIME
+        $this_day_result .= $Config{"show_time"} =~ /^y/i
+                 ? "$hour:$min:$sec"
+                 : "";
 
-        # COMMAND
-        $Result{"body"} .= "\n";
-        $Result{"body"} .= "
\n";
-        my $cline = $cl->{"prompt"}.$cl->{"cline"};
+# COMMAND
+        my $hint = make_comment($cl->{"cline"});
+
+        my $cline;
+        $cline = $cl->{"prompt"}.$cl->{"cline"};
         $cline =~ s/\n//;
 
-        #$cline .= "(".$Sessions{$cl->{local_session_id}}.")";
-        
-        my $hint = make_comment($cl->{"cline"});
         $cline = "$cline" if $hint;
         $cline = "$cline" if !$hint;
-        $Result{"body"} .= $cline;
-        $Result{"body"} .= "
\n"; + $this_day_result .= "\n"; + $this_day_result .= "
\n" . $cline . "
\n"; + +# OUTPUT my $last_command = $cl->{"last_command"}; if (!( $Config{"suppress_editors"} =~ /^y/i && grep ($_ eq $last_command, @{$Config{"editors"}}) || $Config{"suppress_pagers"} =~ /^y/i && grep ($_ eq $last_command, @{$Config{"pagers"}}) || $Config{"suppress_terminal"}=~ /^y/i && grep ($_ eq $last_command, @{$Config{"terminal"}}) )) { - - $Result{"body"} .= "
";
-            $Result{"body"} .= $output;
-            $Result{"body"} .= "
\n"; + $this_day_result .= "
" . $output . "
\n"; } - # DIFF +# DIFF if ( $Config{"show_diffs"} =~ /^y/i && $cl->{"diff"}) { - $Result{"body"} .= "
";
-            $Result{"body"} .= $cl->{"diff"};
-            $Result{"body"} .= "
"; + $this_day_result .= "
"
+                    .  $cl->{"diff"}
+                    .  "
"; } - - #NOTES + +#NOTES if ( $Config{"show_notes"} =~ /^y/i && $cl->{"note"}) { my $note=$cl->{"note"}; $note =~ s/\n/\n/msg; if (not $note =~ s@(http:[a-zA-Z.0-9/_?%-]*)@$1@g) { - $note =~ s@(www\.[a-zA-Z.0-9/_?%-]*)@$1@g; - }; + $note =~ s@(www\.[a-zA-Z.0-9/_?%-]*)@$1@g; + }; # Ширину пока не используем - # $Result{"body"} .= ""; - $Result{"body"} .= "
"; - $Result{"body"} .= "" if $cl->{note_title}; - $Result{"body"} .= ""; - $Result{"body"} .= "
".$cl->{note_title}."
".$note."
\n"; + # $this_day_result .= ""; + $this_day_result .= "
"; + $this_day_result .= "" if $cl->{note_title}; + $this_day_result .= ""; + $this_day_result .= "
".$cl->{note_title}."
".$note."
\n"; } - # COMMENT +# COMMENT if ( $Config{"show_comments"} =~ /^y/i) { my $comment = make_comment($cl->{"cline"}); if ($comment) { - $Result{"body"} .= "". - "
"; - $Result{"body"} .= ""; - $Result{"body"} .= $comment; - $Result{"body"} .= "
\n"; - $Result{"body"} .= "
"; + $this_day_result .= "
" + . "" + . $comment + . "
\n" + . "
"; } } # Вывод очередной команды окончен - $Result{"body"} .= "\n"; - $Result{"body"} .= "\n"; + $this_day_result .= "\n"; + $this_day_result .= "\n"; } - $Result{"body"} .= "\n"; + $result .= "

".$Day_Name[$last_wday]."

"; + $result .= "\n"; + $result .= $this_day_result; + $result .= "
"; - #$Result{"stat"} = "
"; + return ($result, collapse_list (\@toc)); +} + + + + +############# +# print_all +# +# +# +# In: $_[0] output_filename +# Out: + + +sub print_all +{ + my $output_filename=$_[0]; + + my $result; + my ($command_lines,$toc) = print_command_lines; + + $result = print_header($toc); + $result.= "

Журнал

" . $command_lines; + $result.= "

Статистика

" . print_stat; + $result.= "

Справка

" . $Html_Help . "
"; + $result.= "

О программе

". $Html_About. "
"; + $result.= print_footer; + + if ($output_filename eq "-") { + print $result; + } + else { + open(OUT, ">", $output_filename) + or die "Can't open $output_filename for writing\n"; + print OUT $result; + close(OUT); + } +} + +############# +# print_header +# +# +# +# In: $_[0] Содержание +# Out: Распечатанный заголовок + +sub print_header +{ + my $toc = $_[0]; + my $course_name = $Config{"course-name"}; + my $course_code = $Config{"course-code"}; + my $course_date = $Config{"course-date"}; + my $course_center = $Config{"course-center"}; + my $course_trainer = $Config{"course-trainer"}; + my $course_student = $Config{"course-student"}; + + my $title = "Журнал лабораторных работ"; + $title .= " -- ".$course_student if $course_student; + if ($course_date) { + $title .= " -- ".$course_date; + $title .= $course_code ? "/".$course_code + : ""; + } + else { + $title .= " -- ".$course_code if $course_code; + } + + # Управляющая форма + my $control_form .= "
Видимые элементы
\n"; + for my $element (keys %Elements_Visibility) + { + my @e = split /\s+/, $element; + my $showhide = join "", map { "ShowHide('$_');" } @e ; + $control_form .= "". + $Elements_Visibility{$element}. + "
\n"; + } + $control_form .= "
\n"; + + my $result; + $result = < + + + + $title + + + +

Журнал лабораторных работ

+HEADER + if ( $course_student + || $course_trainer + || $course_name + || $course_code + || $course_date + || $course_center) { + $result .= "

"; + $result .= "Выполнил $course_student
" if $course_student; + $result .= "Проверил $course_trainer
" if $course_trainer; + $result .= "Курс " if $course_name + || $course_code + || $course_date; + $result .= "$course_name " if $course_name; + $result .= "($course_code)" if $course_code; + $result .= ", $course_date
" if $course_date; + $result .= "Учебный центр $course_center
" if $course_center; + $result .= "

"; + } + + $result .= < + + + + + + + +
+
Содержание
+ +
+ + + $control_form + + +HEADER + + return $result; +} + + +############# +# print_footer +# +# +# +# +# + +sub print_footer +{ + return "\n\n"; +} + + + + +############# +# print_stat +# +# +# +# In: +# Out: + +sub print_stat +{ %StatNames = ( - FirstCommand => "Время первой команды журнала", - LastCommand => "Время последней команды журнала", - TotalCommands => "Количество командных строк в журнале", - ErrorsPercentage => "Процент команд с ненулевым кодом завершения, %", - TotalTime => "Суммарное время работы с терминалом *, час", - CommandsPerTime => "Количество командных строк в единицу времени, команда/мин", - CommandsFrequency => "Частота использования команд", - RareCommands => "Частота использования этих команд < 0.5%", + FirstCommand => "Время первой команды журнала", + LastCommand => "Время последней команды журнала", + TotalCommands => "Количество командных строк в журнале", + ErrorsPercentage => "Процент команд с ненулевым кодом завершения, %", + MistypesPercentage => "Процент синтаксически неверное набранных команд, %", + TotalTime => "Суммарное время работы с терминалом *, час", + CommandsPerTime => "Количество командных строк в единицу времени, команда/мин", + CommandsFrequency => "Частота использования команд", + RareCommands => "Частота использования этих команд < 0.5%", ); @StatOrder = ( FirstCommand, LastCommand, TotalCommands, ErrorsPercentage, + MistypesPercentage, TotalTime, CommandsPerTime, CommandsFrequency, @@ -671,8 +825,10 @@ $Stat{FirstCommand} = sprintf "%02i:%02i:%02i %04i-%2i-%2i", $hour, $min, $sec, $year+1900, $mon+1, $mday; ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($Stat{LastCommand} || 0); $Stat{LastCommand} = sprintf "%02i:%02i:%02i %04i-%2i-%2i", $hour, $min, $sec, $year+1900, $mon+1, $mday; - $Stat{ErrorsPercentage} = sprintf "%5.2f", $Stat{ErrorCommands}*100/$Stat{TotalCommands} - if $Stat{TotalCommands}; + if ($Stat{TotalCommands}) { + $Stat{ErrorsPercentage} = sprintf "%5.2f", $Stat{ErrorCommands}*100/$Stat{TotalCommands}; + $Stat{MistypesPercentage} = sprintf "%5.2f", $Stat{MistypedCommands}*100/$Stat{TotalCommands}; + } $Stat{CommandsPerTime} = sprintf "%5.2f", $Stat{TotalCommands}*60/$Stat{TotalTime} if $Stat{TotalTime}; $Stat{TotalTime} = sprintf "%5.2f", $Stat{TotalTime}/60/60; @@ -688,14 +844,16 @@ if ($percentage < 0.5) { my $hint = make_comment($command); $command_html = "$command"; - $command_html = "$command_html" if $hint; + $command_html = "$command_html" if $hint; + $command_html = "$command_html" if not $hint; my $command_html = "$command_html"; $Stat{RareCommands} .= $command_html."".$CommandsFrequency{$command}." , "; } else { my $hint = make_comment($command); $command_html = "$command"; - $command_html = "$command_html" if $hint; + $command_html = "$command_html" if $hint; + $command_html = "$command_html" if not $hint; my $command_html = "$command_html"; $percentage = sprintf "%5.2f",$percentage; $Stat{CommandsFrequency} .= "".$command_html."".$CommandsFrequency{$command}."". @@ -706,106 +864,20 @@ $Stat{RareCommands} =~ s/, $// if $Stat{RareCommands}; } - $Result{"stat"} .= "

Статистика

"; - $Result{"stat"} .= ""; + my $result = q(); for my $stat (@StatOrder) { - $Result{"stat"} .= "" - if $Stat{"$stat"}; + next unless $Stat{"$stat"}; + $result .= "" } - - $Result{"stat"} .= "
".$StatNames{"$stat"}."".$Stat{"$stat"}."
".$StatNames{"$stat"}."".$Stat{"$stat"}."
"; - $Result{"stat"} .= "____
*) Интервалы неактивности длительностью ".($Config{stat_inactivity_interval}/60)." минут и более не учитываются

"; + $result = "$result
" + . "____
*) Интервалы неактивности длительностью " + . ($Config{stat_inactivity_interval}/60) + . " минут и более не учитываются

"; - #$Result{"help"} .= "
"; - $Result{"help"} .= "

Справка

"; - $Result{"help"} .= "$Html_Help
"; - #$Result{"about"} .= "
"; - $Result{"about"} .= "

О программе

"; - $Result{"about"} .= "$Html_About"; - $Result{"footer"} .= "\n"; - $Result{"footer"} .= "\n"; - - $Result{"title"} = "Журнал лабораторных работ"; - $Result{"title"}.= " -- ".$course_student if $course_student; - if ($course_date) { - $Result{"title"}.= " -- ".$course_date; - $Result{"title"}.= "/".$course_code if $course_code; - } - else { - $Result{"title"}.= " -- ".$course_code if $course_code; - } - - # Заголовок генерируется позже всего - # Тогда, когда известно уже, что должно быть написано в - # оглавлении - $Result{"header"} = < - - - - $Result{title} - - - -

Журнал лабораторных работ

- -HEADER - $Result{"header"} .= "

" if $course_student || $course_trainer || $course_name || $course_code || $course_date || $course_center; - $Result{"header"} .= "Выполнил $course_student
" if $course_student; - $Result{"header"} .= "Проверил $course_trainer
" if $course_trainer; - $Result{"header"} .= "Курс " if $course_name || $course_code || $course_date; - $Result{"header"} .= "$course_name " if $course_name; - $Result{"header"} .= "($course_code)" if $course_code; - $Result{"header"} .= ", $course_date
" if $course_date; - $Result{"header"} .= "Учебный центр $course_center
" if $course_center; - $Result{"header"} .= "

" if $course_student || $course_trainer || $course_name || $course_code || $course_date || $course_center; - - my $toc = collapse_list (\@toc); - $Result{"header"} .= < - - -
Содержание
- - - - - -

Журнал

-HEADER - $Result{"header"} .= "
\n"; - for my $element (keys %Elements_Visibility) - { - my @e = split /\s+/, $element; - my $showhide = join "", map { "ShowHide('$_');" } @e ; - $Result{"header"} .= "". - $Elements_Visibility{$element}. - "
\n"; - } - - $Result{"header"} .= "
\n"; - - if ($output_filename eq "-") { - print $Result{"header"}, $Result{"body"}, $Result{"stat"}, $Result{"help"}, $Result{"about"}, $Result{"footer"}; - } - else { - open(OUT, ">", $output_filename) - or die "Can't open $output_filename for writing\n"; - print OUT $Result{"header"}, $Result{"body"}, $Result{"stat"}, $Result{"help"}, $Result{"about"}, $Result{"footer"}; - close(OUT); - } + return $result; } - sub collapse_list($) { my $res = ""; @@ -831,7 +903,7 @@ всё происходит само собой. Однако, чтобы ведение и последующее использование журналов было как можно более эффективным, желательно иметь в виду следующее: -
    +
    1. В журнал автоматически попадают все команды, данные в любом терминале системы.

    2. @@ -1020,7 +1092,7 @@ добавляются точно таким же способом, только вместо симолов #^ или #v нужно использовать символы #=

      -
+ HELP $Html_About = <"; +} +