#!/usr/bin/perl -w
# This script (examplix) was created by Rüdiger Beck
# It is released under the GPL Version 3
# For Bugs send mail to:
# jeffbeck@web.de

# Bibliotheken
use strict;
use Getopt::Long;
use Examplix::ExamplixConfig;
use Spreadsheet::WriteExcel;
use Spreadsheet::ParseExcel;
use Regexp::Common;
use POSIX;
use File::Basename;
use utf8;
use Text::Iconv;

my $log_level=1;
my $show_birthcity=0;

# encoding og students.txt
my $coding="utf8";

my $home = $ENV{'HOME'};
my $prefix="${home}/examplix";
my $prefix_work="${home}/examplix";
if (-l $prefix){
    my $source = readlink $prefix;
    print "$prefix is a link to $source\n";
    $prefix = $source;
} 
if (-l $prefix_work){
    my $source = readlink $prefix_work;
    print "$prefix_work is a link to $source\n";
    $prefix_work = $source;
} 

$prefix=$prefix."/";
$prefix_work=$prefix_work."/";

print "$prefix\n";
print "$prefix_work\n";

my $skip_md5sum_check=0;

my @dummy_users=("Albert"," Brigitte","Conrad","Doro");

# git messages
my $git_revision_control="Git Revision Control!";
my $no_git_revision_control="NOT under Git Revision Control!";
my $no_remote_string="Git: No remote defined!";

# git remote (put that in config file later)

# clone a repo this way:
# git clone jeffbeck:examplix/m3kk3t_Jahr_2011-2012

# key that is preloaded because LTS 10.04 GUI asks for the wrong key 
my $git_ssh_config_preload_key="jeffbeck";
my $git_ssh_config_entry="jeffbeck";
# .ssh/config looks like:
# Host jeffbeck
#    HostName cvs.bszleo.de
#    User gitolite
#    IdentityFile ~/.ssh/jeffbeck


# configure this
# factor for exams
my $exam_factor=2;
# factor for registration marks (Anmeldenoten)
my $reg_mark_factor=1;

my %examplix_types=qw(P-T1  yes
                      P-T2  yes
                      Jahr  yes
                     );


# which EXAMONLY_SUBJECT refers to which SUBJECT (i.e. WSK > WK)
my %examonly_subject_references=qw();


my @mark_types=("KA","HA","Test","M");
my $mark_types_count=$#mark_types+1;

my %kammer_marks=();

my %mark_types_count=qw(HA 10 
                        KA 5
                        Test 5
                        M 5
                       );

# Define the headers
my @group_headers=("G1","G2","G3","G4","G5","G6","G7","G8","G9");

my $create="";
my $kill="";
my $pull="";
my $class="";
my $atlantisfile="";
my $teacher_opt="";
my $teacher="";
my $tasks="";
my $import="";
my $update="";
my $result="";
my $inotify="";
my $pro_name="";
my $help=0;
my $force=0;
my $list=0;
my $create_lists="";
my $encrypt_all=0;
my $decrypt="";
# decided automatically:
my $year=0;
my $midyear=0;
# given by option:
my $year_opt=0;
my $midyear_opt=0;

my $exam=0;
my $exam_opt=0;
my $single_correction=0;
my $viewer=1;
my $mode="";
my $final_version=0;
my $landscape=0;
my $narrow=0;

my %hash=();


my @students=();
my %students=();
my %students_class=();
my $students_num=0;
my %teachers_seen=();

my @subjects=();
my @problems=();
my @averages_class=();
my $average_class=0;
my @sums_class=();
my @sums_students_with_result=();
my $sum_students_with_average=0;
my $sum_class=0;
     
my @days=();     
my @factors=();     

my $max_problems=7;

my %translate_key_short=();
my %translate_key_long=();

my @all_users=();
my %all_users=();

# hash of hash of hash ...
my %metadata_teacher_level=();
my %user_teacher_level=();


# hash of hash of hash ...
my %all_marks=();

# hash of registration marks
my %reg_marks=();

my %all_correctors=();

my @numstrings=();

my @final_subjects = ();
my @final_subjects_loop = ();
my @final_subjects_show = ();
my %subject_type = ();
my %typeout=();
my @final_list=();

my $final_list_ref=\@final_list;

my %examonly_subject=();

my %valid_final_marks = qw(
   1,0  1
   2,0  2
   3,0  3
   4,0  4
   5,0  5
   6,0  6
);

my %valid_marks = qw(
   1    1
   1.0  1
   1.1  1
   1.2  1
   1.3  1
   1.4  1
   1.5  2
   1.6  2
   1.7  2
   1.8  2
   1.9  2
   2    2
   2.0  2
   2.1  2
   2.2  2
   2.3  2
   2.4  2
   2.5  3
   2.6  3
   2.7  3
   2.8  3
   2.9  3
   3    3
   3.0  3
   3.1  3
   3.2  3
   3.3  3
   3.4  3
   3.5  4
   3.6  4
   3.7  4
   3.8  4
   3.9  4
   4    4
   4.0  4
   4.1  4
   4.2  4
   4.3  4
   4.4  4
   4.5  5
   4.6  5
   4.7  5
   4.8  5
   4.9  5
   5    5
   5.0  5
   5.1  5
   5.2  5
   5.3  5
   5.4  5
   5.5  6
   5.6  6
   5.7  6
   5.8  6
   5.9  6
   6    6
   6.0  6
);


# Kammerschluessel: Bestmoegliche Punktzahl
my %kammer_key = qw(
   1    100
   1.0  100
   1.1  98
   1.2  96
   1.3  94
   1.4  92
   1.5  91
   1.6  90
   1.7  89
   1.8  88
   1.9  87
   2    85
   2.0  85
   2.1  84
   2.2  83
   2.3  82
   2.4  81
   2.5  80
   2.6  79
   2.7  77
   2.8  76
   2.9  74
   3    73
   3.0  73
   3.1  71
   3.2  70
   3.3  68
   3.4  67
   3.5  66
   3.6  64
   3.7  62
   3.8  61
   3.9  59
   4    57
   4.0  57
   4.1  55
   4.2  54
   4.3  52
   4.4  50
   4.5  49
   4.6  47
   4.7  45
   4.8  43
   4.9  41
   5    38
   5.0  38
   5.1  36
   5.2  34
   5.3  32
   5.4  30
   5.5  29
   5.6  28
   5.7  22
   5.8  16
   5.9  11
   6    5
   6.0  5
);






my %valid_override_marks = qw(1 valid 
                              2 valid 
                              3 valid 
                              4 valid 
                              5 valid
                              6 valid
                             );

# hash with old_user_name --> new_user_name
my %student_updates=();

my $not_taken_string="*)";
my %not_taken_comments = (
   -2000 => "$not_taken_string Zweitausbildung",
   -3000 => "$not_taken_string Fachhochschulreife",
   -4000 => "$not_taken_string Hochschulreife",
   -5000 => "$not_taken_string Manag. im Handwerk",
);

# List of part of years
# "teil1","Teil2","Teil3"
my @year_part_list=("Halbjahr","Schuljahr");
my $latex_title="";

# how many of the parts are maximal
my $max_part=6;


# Parsen der Optionen
my $testopt=GetOptions(
           "verbose|v+" => \$log_level,
           "create|c=s" => \$create,
           "kill=s" => \$kill,
           "pull=s" => \$pull,
           "class=s" => \$class,
           "atlantisfile=s" => \$atlantisfile,
           "teacher=s" => \$teacher_opt,
           "tasks|t=s" => \$tasks,
#           "import=s" => \$import,
           "inotify=s" => \$inotify,
#           "update=s" => \$update,
           "result|r=s" => \$result,
           "help|h" => \$help,
           "coding=s" => \$coding,
           "force" => \$force,
           "list|l" => \$list,
           "create-lists=s" => \$create_lists,
           "encrypt-all|encrypt" => \$encrypt_all,
           "decrypt=s" => \$decrypt,
           "year" => \$year_opt,
           "midyear" => \$midyear_opt,
           "exam" => \$exam_opt,
           "single-correction" => \$single_correction,
           "skip-md5sum-check" => \$skip_md5sum_check,
           "viewer!" => \$viewer,
           "final" => \$final_version,
           "narrow" => \$narrow,
          );



# Prüfen, ob Optionen erkannt wurden, sonst Abbruch
&check_options($testopt);

# 
if ($year_opt==1 and $midyear_opt==1){
    print "\nYou cannot use option --year and --midyear together\n\n";
    exit;
}


# --help
if ($help==1) {
   # Scriptname ermitteln
   my @list = split(/\//,$0);
   my $scriptname = pop @list;
   # Befehlsbeschreibung
   print('
examplix (EXAMs Per LInux/uniX) is a tool to divide the correction of a larger exam into smaller chunks for a number of people and put together these chunks and calsulate a mark.  

Options
  -h  / --help
  -v  / --verbose
  -vv / --verbose --verbose

What type of calculation:
  --year, --midyear (what to calculate)  
  --exam 
  --exam --single-correction (print final results for first corrector only)

What to do:
  Create a project:
   -c / --create name --class class1,class2,class3,...
   -c / --create name --class class1,... --atlantisfile /path/file 
   Other options that MUST be given:
      --teacher class-teacher
  Create tasks for an existing  project:
   -t / --tasks name
   -t / --tasks name --force (override existing files)
  Calculate results of an existing  project:
   -r / --result name
   Other Options:
      --final (Do not use underlying Text on printout)
  Working on an Projekt on a different PC:
  Load the ssh-key for the examplix-git-server and then:
   --pull name
  Create correction lists (exams only):
   --create-lists name

  Delete a project:
   --kill name

Formatting:
  --narrow (Format landscape tables more narrow to fit more columns)
  --coding Sets the latex inputenc field
  
Encryption:
  -l / --list (list decrypted/encrypted projects)
  --encrypt (encrypt all decrypted projects)
  --decrypt name

Managing student names:
  * Remove a user from final list:
     add a # before the user in students.cfg
  * Rename a user:
     add a == after user, copy entry behind == and edit the name, ...


Example Schulklasse:
  1) Create Project:
     examplix -c m1kk3t_Jahr_2010-2011
              --class M1KK3T
              --atlantisfile /abs/path/to/file/schueler.txt
              --teacher jeffbeck
  2) Edit year.cfg
  3) Create Task files:
     examplix -t m1kk3t_Jahr_2010-2011
  4) Add marks in project/collect
  5) Generate results:
     examplix -r m1kk3t_Jahr_2010-2011 --year/--midyear

Example Exam:
  1) Create Project:
     examplix -c exam_P-T1_Sommer-2012
              --class M2KK1T,M2KK2T,M2KK3T,M2KK4T
              --atlantisfile /abs/path/to/file/schueler.txt
              --teacher jeffbeck
  2) Edit exam.cfg
  3) Create Task files:
     examplix -t exam_P-T1_Sommer-2012
  4) Add marks in project/collect
  5) Generate results:
     examplix -r exam_P-T1_Sommer-2012 --exam

Hints: ONLY small letters alowed for class/exam name.




Please see the examplix(1) man pages for full documentation
');
   print "\n";
   exit;
}

my $dev_null;
if($log_level>=3){
    $dev_null="";
} else {
    $dev_null="> /dev/null";
}

# --list
if ($list==1){
    print "##### Decrypted Projects in $prefix: #####\n";
    my @decrypted=&fetch_projects("DECRYPTED");
    @decrypted = sort @decrypted;
    foreach my $project (@decrypted){
        my $remote = &fetch_remote($project);
        printf "  %-24s%-50s\n",$project,$remote;
    }
    print "##### Encrypted Projects in $prefix: #####\n";
    my @encrypted=&fetch_projects("ENCRYPTED");
    @encrypted = sort @encrypted;
    foreach my $project (@encrypted){
        my $remote = &fetch_remote($project);
        printf "  %-24s%-50s\n", $project, $remote;
    }
    exit;
}



# --encrypt-all/--encrypt
if ($encrypt_all==1){
    &encrypt_decrypted_projects();
    exit;
}

# --decrypt name
if ($decrypt ne ""){
    ($year,$midyear,$exam)=&check_name($decrypt,"AUTOGIT");
    &check_decryption($decrypt);
    exit;
}



# --Year
if ($year_opt==1 or $midyear_opt==1){
    &set_mode("year");
}


# --exam
if ($exam==1){
    &set_mode("exam");
}





&get_translation();

# --pull
if ($pull ne ""){
    my $abs_pro=$prefix."".$pull;
    my $abs_pro_dot=$prefix.".".$pull;
    print "Pulling project $abs_pro\n";
    if (-d $abs_pro_dot){
        print "$pull was cloned already.\n";
        print "Pulling changes:\n";
        my $command="cd $abs_pro_dot; ".
                    "git pull origin master";
        print "$command\n";
        print "\nPassword for the user in the identity ",
              "file ~/.ssh/config";
        my $return=system("$command");
        if ($return==0){
            print "\nGit update was successful\n\n";
        } else {
            print "\nWARNING: Git update was NOT successful\n\n";
        }
    } else {
        print "$pull not found.\n";
        print "Cloning $pull:\n";
        system("mkdir -p $prefix");
        my $command="cd $prefix; ".
                    "git clone ${git_ssh_config_entry}:examplix/$pull .$pull";
        print "$command\n";
        system("$command");
    }
    exit;
}

# --create
if ($create ne "") {
  ($year,$midyear,$exam)=&check_name($create);
  $pro_name=$create;
  # 
  if ($teacher_opt eq ""){
      print "\nYou must use --teacher name to specify a class-teacher\n\n";
      exit;
  }
  #
  if (-e $create){
      print "\nERROR: \n",
            "   Exam-Directory $create exists already\n",
            "   I'm doing nothing!\n\n";
      exit;
  }
  if ($class eq ""){
      # check if I run on a sophomorix server
      if (-x "/usr/sbin/sophomorix-print"){
          print "\nHint: You can use --class class1,class2,... to fetch",
                " a list of students.\n\n";
          exit;
      }
  } elsif ($class ne  "" and -e $atlantisfile) {
      # thats OK
  } else {
      if (not -x "/usr/sbin/sophomorix-print"){
          print "\nHint: The script to fetch a list of students is ",
                "nonexisting or not executable.\n";
          print "You cannot run examplix with option --class on this system.\n\n";
          exit;
      }
  }
  &create_exam($create); 
}



# --kill
if ($kill ne "") {
    ($year,$midyear,$exam)=&check_name($kill);
    $pro_name=$kill;
    print "\n############################################################\n";
    print "WARNING: The project $kill will be removed permanently!\n";

    # check if project is under git

    # dismount
    my $abs_pro=$prefix."".$kill;
    my $abs_pro_dot=$prefix.".".$kill;

    print "   Deleting: $abs_pro\n";
    print "   Deleting: $abs_pro_dot\n";
  
    my $umount="fusermount -u $abs_pro";
    my $kill_1="rm -rf $abs_pro";
    my $kill_2="rm -rf $abs_pro_dot";


    # git remote
    my $remote = &fetch_remote($kill);
    if ($remote ne $no_remote_string){
        print "\nWARNING: There is a remote git existing\n\n";

        # Todo: ask to remove the remote also

    }

    # ask again
    my $kill_it="";
    print "\nDo you really want to delete ${kill}?\n(y/n):";
    while(){# Endlosschleife für die Eingabe
        $kill_it= <STDIN>; # Lesen von Tastatur
        chomp($kill_it); # Newline abschneiden
        if ($kill_it eq "y"){
            # encrypt
            print "        $umount\n";
            system($umount);
            # delete files
            print "        $kill_1\n";
            system($kill_1);
            print "        $kill_2\n";
            system($kill_2);
            last;
        } else {
            print "\nDeletion canceled!\n\n";
            last;
        }
    }
    exit;
}


# --tasks
if ($tasks ne "") {
    ($year,$midyear,$exam)=&check_name($tasks);
    &check_decryption($tasks);
    $pro_name=$tasks;
    #$mode = &fetch_mode($tasks);
    @students=&get_students($tasks,$teacher);
    %hash = &create_task_hash($tasks,$teacher);
    print "Creating the following Collect-Files of exam $tasks:\n";
    while (my ($file,$prob) = each %hash ){
        print "   $file with Problems: $prob \n";
        my ($user) = split(/_/,$file);
        if ($mode eq "exam"){
            # 
            &create_xls_file($file,$prob,"EXAM");
        } else {
            # class teacher level
            &create_xls_file($file,$prob,"OVERRIDE");
        }

        # teacher level
        if ($year==1 or $midyear==1){
            &create_xls_file($file,$prob,"NOTEN",25);
        }
    }

    if ($exam==1){
        &create_xls_reg_mark_file("exam");
    } else { 
        &create_xls_reg_mark_file("year");
        &create_xls_reg_mark_file("midyear");
    }

    &create_xls_groups_file();
    if ($mode eq "exam"){
	print "Creating empty lists\n";
        system ("mkdir -p ${prefix}$tasks/lists");     
        &create_lists($tasks);
    }
}



# --create-lists
if ($create_lists ne ""){
    ($year,$midyear,$exam)=&check_name($create_lists,"AUTOGIT");
    &check_decryption($create_lists);
    if ($mode eq "exam"){
	print "Creating empty lists for $create_lists\n";
        system ("mkdir -p ${prefix}$create_lists/lists");     
        &create_lists($create_lists);
    } else {
        print "\nNo lists to create (Auto-Mode is $mode)\n\n";
    }
    exit;
}



# --result
if ($result ne "") {
  ($year,$midyear,$exam)=&check_name($result,"AUTOGIT");
  # when mode is year, then --year or --midyear must be given
  print "$exam, $year, $midyear\n\n";
  if ( 
      ($year==1 or $midyear==1) and
      ($year_opt==0 and $midyear_opt==0)
     ){
      print "\nWhat should be calculated?\n   --year\n   --midyear\n\n";
      exit;
  }
  &check_decryption($result);
  $pro_name=$result;
  @final_subjects = &get_all_subjects();
  @final_subjects_loop = &get_loop_subjects();
  @final_subjects_show = &get_show_subjects();

  %subject_type=&get_show_subjects("hash");
  %typeout=&read_typeout();
  while (my ($file,$prob) = each %typeout ){
      print "$file  $prob\n";
  }
  sleep 1;
  @days = &get_days();

  %hash = &create_task_hash($result);

  if ($year==1 or $midyear==1){
      # create teacher level *.ps and *.pdf
      while (my ($file,$prob) = each %hash ){
          my ($abs_file,$teacher)=&abs_path_xls_file_teacher($file);
          my $to_be_updated=&md5sum_file_changed($abs_file);
          my $xls_file=&read_xls_file_teacher("$abs_file",$teacher);
          if ($to_be_updated==1){
              print "\nCalculating results for ($to_be_updated):\n $abs_file\n";
              my $latex_file=&create_latex_file_teacher($xls_file);
              &compile_latex_file($latex_file);
          }
      }
  }


# ALLE Ergebnisse der teacher-level Dateien sind in 
# %metadata_teacher_level{"test-class"}....
  
  #if ($year==1){
  #   # read the data of teacher level
  #   &read_results_teacher();
  #}



  # create big hash
  # Daten sind schon eingelesen
  # wird für $corr benötigt ???????????????? was sonst noch, 
  # kann man dieses nochmalige einlesen weglassen ?????
  while (my ($file,$prob) = each %hash ){
      &read_xls_file($file,$prob,"NOTEN");
  }

  # create reg_mark_hash
  # liest override_Halbjahr/Schuljahr.xls bzw. Anmeldenoten_all.xls
  # in %reg_marks
  &read_xls_reg_mark_file();

  # create dir if not there already
  if (not -e "${prefix}$result/results/${mode}"){
      system ("mkdir -p ${prefix}$result/results/${mode}");     
  }
  # create dir if not there already
  if (not -e "${prefix}$result/collect/${mode}"){
      system ("mkdir -p ${prefix}$result/collect/${mode}");     
  }

  &latex_preamble();

  @subjects = &get_all_subjects();

  my @stud_res=&get_students($result);
  $students_num=$#stud_res+1;

  print LATEX "\\newpage\n";

  if ($exam==1){
      print LATEX "\\section{Korrektur-Ergebnisse ($latex_title)}\n";
  } else{
      print LATEX "\\section{Fachnoten ($latex_title)}\n";
  } 

  # compile class teacher list
  # Number of subjects
  my $i_sub=0;
  foreach my $sub (@subjects){
    $i_sub++;
    # subject selected
    my $cline_max;
    @averages_class=();
    $average_class=0;
    @sums_class=();
    @sums_students_with_result=();
    $sum_students_with_average=0;
    $sum_class=0;

    print "\n##### Creating Results of subject $sub ...\n";
    &set_data_for_subject($sub);

    # hack: if Erstkorrektur, then dont go for average
    &latex_headers($sub,$numstrings[0],$i_sub);
    my $i=0;
    foreach my $student (@stud_res){
      # go through all students

      if($log_level>=2){
         print "    Student $student\n";
      }
      my $average_1=0;
      my $average_1_format="";
      my $average_2=0;
      my $average_2_format="";
      my $average_3=0;
      my $average_3_format="";
      my $missing_1=0;
      my $missing_2=0;
      my $missing_3=0;
      my %marks=();      

      my $student_name="";
      if (exists $student_updates{$student}){
          # mapping exists 
	  $student_name=$student_updates{$student};
      } else {
          $student_name=$student;   
      }

      my ($last,$first)=split(/,/,$student_name);

      # check if it's a dummy student (last name = class)
      # class of student
      my $class = $students_class{$student_name};
      #print "Last: $last First: $first    in $class\n";
      if ($last eq $class){
          # a dummy user
          next;
      }

      # increase student counter
      $i++;

      # remove space in the beginning
      $first =~ s/^ //;

      foreach my $num (@numstrings){
         # go through all lines for a student (Erst., Zweit.,  Dritt, ...)
         if($log_level>=3){
            print "     * $num ...\n";
	 }
         my $sum=0;
         my $divisor=0;
         my $all_average=0;
         my $all_average_single_correction=0;

         my $line="";
         # print student name
         if ($narrow==1 and $landscape==1){
             # shorten the Name to $num chars when they are larger than $num+1
             # No need to shorten string, when it has $num+1 chars
             my $num=4;
             if (length($last) > $num+1){
                 if ($last=~m/[mM]/){
                     # use one char less when broad letters like Mm are in string
                     substr($last,$num-1,100,"*");
		 } else {
                     substr($last,$num,100,"*");
		 }
             }
             if (length($first) > $num+1){
                 if ($first=~m/[mM]/){
                     # use one char less when broad letters like Mm are in string
                     substr($first,$num-1,100,"*");
		 } else {
                     substr($first,$num,100,"*");
                 }
             }
         }
         if ($num eq "Erstkorrektur"){
            if ($narrow==1 and $landscape==1){
                # shortened with \\! an no comma ","
                $line="\\!\\!\\textbf{$i}\\!\\! & \\!\\!\\textbf{".$last."}\\!\\! & ";
            } else {
                $line="\\textbf{$i} & \\textbf{".$last.",} & ";
            }
	 } elsif ($num eq "Zweitkorrektur"){
            if ($narrow==1 and $landscape==1){
                $line="  & \\!\\!\\textbf{".$first."}\\!\\! & ";
            } else {
                $line="  & \\textbf{".$first."} & ";
            }
	 } elsif ($num eq "Drittkorrektur"){
            $line="  & & ";
         } elsif ($num eq "Jahr"){
            $line="\\textbf{$i} & \\rule[-1mm]{0mm}{5mm}\\textbf{".
                  $last.", ".$first."} & ";
         }

         # go through configuration file, determine number of columns
         my $j=0;
         open (CONF, "${prefix_work}$result/${mode}.cfg") || die "Fehler: $!";
         if($log_level>=3){
    	     print "\nOPENING file ${prefix_work}$result/${mode}.cfg\n";
         }
         while (<CONF>){
            s/^ //g; # Leerzeichen am Zeilenangfang entfernen
            if(/^\#/ or 
               /^\s/ or
               /^SHOW_SUBJECT/ or
               /^EXAMONLY_SUBJECT/ or
               /^LOOP_SUBJECT/ or
               /^EXTRA_SUBJECT/ 
              ){ # # am Anfang bedeutet Kommentarzeile
               next;
            }
	    chomp();
            my ($day,
                $problem,
                $subject,
                $factor,
                $corr_1,
                $group_1,
                $corr_2,
                $group_2,
                $corr_3,
                $group_3)=split(/;/);
            my $corrector;
            if ($num eq "Erstkorrektur"){
		$corrector=$corr_1;
            } elsif ($num eq "Zweitkorrektur"){
		$corrector=$corr_2;
            } elsif ($num eq "Drittkorrektur"){
		$corrector=$corr_3;
            } else {
                # mid-year and year
		$corrector=$corr_1;
            }             

            if ($subject eq $sub) {
               # create a column
               if($log_level>=3){
	          print "    FOUND Subject ${sub}\n";
	       }
               my @result = &get_result_fromhash($student,
                                                 $corrector,
                                                 $subject,
                                                 $num,
                                                 $day,
                                                 $problem);

               if($log_level>=3){
                  print "    * $result[0] $problem of $student corrected",
                        " by $result[2] is $result[3] \n";
	       }
               # make a copy of result
               # result[3] is used to calculate average, ...
               # result_format is used as a string to print

               # add the result for averages
 
               ## ????? avoids error
               if (not defined $sums_class[$j]){
                   $sums_class[$j]=0;
               }
               if (not defined $sums_students_with_result[$j]){
                   $sums_students_with_result[$j]=0;
               }

               # if cell contains not a real number (i.e. contains text)
               # convert it to -100 (empty cell)
               if (not $result[3] =~ m{^$RE{num}{real}$}) {
                   $result[3]=-100;
               } elsif ($result[3]>0){   
	           $sums_class[$j]=$result[3]+$sums_class[$j];
	           $sums_students_with_result[$j]=1+$sums_students_with_result[$j];
               }

               my $result_format=&format($result[3]);
               if ($num eq "Erstkorrektur"){
                   if ($result[3]==-100){
                      $line = $line."   \\colorbox{red}{\\!---\\!} &";
                      $missing_1=1;
                   } elsif ($result[3]==-200) {
                      $line = $line."   \\colorbox{red}{\\!NF\\!} &";
                      $missing_1=1;
                   } elsif ($result[3]==-300) {
                      $line = $line."   \\textcolor{red}{\\!---\\!} &";
                      #$missing_1=1;
                   } else {
                          $line = $line."   \\textcolor{red}{\\!".
                                  $result_format."\\!} &";
                   }
               } elsif ($num eq "Zweitkorrektur"){
                   if ($result[3]==-100){
                      $line = $line."   \\colorbox{green}{\\!---\\!} &";
                      $missing_2=1;
                   } elsif ($result[3]==-200) {
	              if ($single_correction==0){
                          $line = $line."   \\colorbox{green}{\\!NF\\!} &";
                      } else {
                          # do not show anything distractive
                          $line = $line." &";
                      }
                      $missing_2=1;
                   } elsif ($result[3]==-300) {
                      $line = $line."   \\textcolor{green}{\\!---\\!} &";
                      #$missing_1=1;
                   } else {                     
                      $line = $line."   \\textcolor{green}{\\!".
                              $result_format."\\!} &";
	           }
               } elsif ($num eq "Drittkorrektur"){
                   if ($result[3]==-100){
                      $line = $line."   \\colorbox{blue}{\\!---\\!} &";
                      $missing_3=1;
                   } elsif ($result[3]==-200) {
                      $line = $line."   \\colorbox{blue}{\\!NF\\!} &";
                      $missing_3=1;
                   } elsif ($result[3]==-300) {
                      $line = $line."   \\textcolor{blue}{\\!---\\!} &";
                      #$missing_1=1;
                   } else {                     
                      $line = $line."   \\textcolor{blue}{\\!".
                              $result_format."\\!} &";
	           }
               } elsif ($num eq "Jahr"){
                   if ($result[3]==-100){
                      $line = $line."   \\colorbox{orange}{---} &";
                      $missing_1=1;
                   } elsif ($result[3]==-200) {
                      $line = $line."   \\colorbox{orange}{NF} &";
                      $missing_1=1;
                   } elsif ($result[3]==-300) {
                      $line = $line."   \\textcolor{orange}{---} &";
                   } elsif ($result[3]==-2000 or
                            $result[3]==-3000 or 
                            $result[3]==-4000 or
                            $result[3]==-5000 ) {
                      $line = $line."   \\colorbox{orange}{---} &";
                      $missing_1=1;
		   } elsif ($result[4]==1){
                      # override -> blue
                      $line = $line."   \\textcolor{blue}{".$result_format."} &";
                   } else {    
                      # no override                 
                      $line = $line."   \\textcolor{orange}{".$result_format."} &";
		   }
               }

               # calculate if result[3] is OK 
               if ($result[3]>0){   
                  $sum = $sum + $result[3]*$factor;
                  $divisor = $divisor + $factor;
	       }
               $j++;
               if($log_level>=3){
                   print "   Subject $sub ($student) Done\n";
               }
           } # end: foreach column

	} # end while 


	 $cline_max=$#problems+4;
         if ($num eq "Erstkorrektur"){
             if ($divisor!=0){
                $average_1 = $sum / $divisor;
	     } else {
                $average_1 = -100;
	     }
             $average_1 = &one_decimal($average_1);	        
             $average_1_format = &format($average_1);
             $sum = &format($sum);
             $line = $line."\\!\\!\\textcolor{red}{".
                     $sum."}\\raisebox{-1mm}{\\tiny $divisor}\\!\\!";
             if ($missing_1==1){
                 if ($narrow==1 and $landscape==1){
                     $line = $line." & \\!\\!\\colorbox{red}{---}\\!\\! &";
                 } else {
                     $line = $line." & \\colorbox{red}{---} &";
                 }
              } else {
                 if ($narrow==1 and $landscape==1){
                     $line = $line." & \\!\\!\\textcolor{red}{".
                             $average_1_format."}\\!\\! &"; 
                 } else {
                     $line = $line." & \\textcolor{red}{".
                             $average_1_format."} &"; 
                 }
                 # save the result for later printing
                 $all_users{$student}{"$sub-1"}=$average_1;
             }

#                $line = $line."\\\\\\cline*{2-${cline_max}} \n";
#                $line = $line."\\\\*\\cline{2-${cline_max}} \n";
# makes no pagebreak
             $line = $line."\\\\* \n";

         } elsif ($num eq "Zweitkorrektur"){
             if ($divisor!=0){
                $average_2 = $sum / $divisor;
	     } else {
                $average_2 = -100;
	     }
             $average_2 = &one_decimal($average_2);
             $average_2_format = &format($average_2);
             $sum = &format($sum);
	     if ($single_correction==0){
                 $line = $line."\\!\\!\\textcolor{green}{".
                         $sum."}\\raisebox{-1mm}{\\tiny $divisor}\\!\\!";
             } else {
                 $line = $line."\\raisebox{-1mm}{}";
             }
             if ($missing_2==1){
		 if ($single_correction==0){
                     if ($narrow==1 and $landscape==1){
                         $line = $line." & \\!\\!\\colorbox{green}{---}\\!\\! &";
                     } else {
                         $line = $line." & \\colorbox{green}{---} &";
                     }
                 } else {
                     $line = $line." & &";
                 } 
	     } else {
                if ($narrow==1 and $landscape==1){
                    $line = $line." & \\!\\!\\textcolor{green}{".
                            $average_2_format."}\\!\\! &";
                } else {
                    $line = $line." & \\textcolor{green}{".
                            $average_2_format."} &";
                } 
  	        # save the result for later printing
	        $all_users{$student}{"$sub-2"}=$average_2;
	     }

             if (defined $numstrings[2]){
                 if ($numstrings[2] eq "Drittkorrektur"){
                     # Drittkorrektur will follow
                     $line = $line."\\\\* \n";
                 } else {
                     print "ERROR: $numstrings[2] \n";
		     exit;
                 }
             } else {
                 # Calculate the average
                 $all_average = 0.5*($average_1 + $average_2 );
                 $all_average = &one_decimal($all_average);
                 # Calculating single correction average
                 $all_average_single_correction = $average_1;
                 $all_average_single_correction = 
                     &one_decimal($all_average_single_correction);
                 # save the result for later printing
                 $marks{"$sub"}=$all_average;               
                 # save it in Anmeldenoten hash for later calculation
                 my $subject_short=&translate_to_short($sub);

                 if ($missing_1==0 
                     and $missing_2==0
                     and not defined $numstrings[2]){
                    $reg_marks{$student}{"exam"}{$subject_short}=$all_average;
                    $all_average = &format($all_average);
                    $line = $line." \\LARGE \\textbf{".$all_average."}";
   	            $all_users{$student}{"$sub-av"}=$all_average;
		 } elsif ($single_correction==1 and $missing_1==0){
                    # single correction
                    $reg_marks{$student}{"exam"}{$subject_short}=
                        $all_average_single_correction;
                    # save it for use in Kammer results
                    $kammer_marks{$student}{$subject_short}=
                        $all_average_single_correction;      
                    $all_average_single_correction = 
                         &format($all_average_single_correction);
                    $line = $line." \\LARGE \\textbf{".$all_average_single_correction."}";
   	            $all_users{$student}{"$sub-av"}=$all_average_single_correction;
                 } else {
                    if ($narrow==1 and $landscape==1){
                        $line = $line." \\LARGE \\!\\!\\textbf{---}\\!\\!"; 
                    } else {
                        $line = $line." \\LARGE \\textbf{---}"; 
                    }
                 }
                 $line = $line."\\\\ \\hline\\hline\\pagebreak[3]\n\n";
	     }

         } elsif ($num eq "Drittkorrektur"){
             if ($divisor!=0){
                $average_3 = $sum / $divisor;
	     } else {
                $average_1 = -100;
	     }
             $average_3 = &one_decimal($average_3);
             $average_3_format = &format($average_3);
             $sum = &format($sum);
             $line = $line." \\textcolor{blue}{".$sum."}";
             if ($missing_3==1){
                $line = $line." & \\colorbox{blue}{---} &"; 
	     } else {
                $line = $line." & \\textcolor{blue}{".$average_3_format."} &"; 
  	        # save the result for later printing
	        $all_users{$student}{"$sub-3"}=$average_3;
	     }

             $all_average = ($average_1 + $average_2 + $average_3)/3;
             $all_average = &one_decimal($all_average);
             # save the result for later printing
             $marks{"$sub"}=$all_average;               
             $all_average = &format($all_average);
             if ($missing_1==0 and $missing_2==0 and $missing_3==0){
                $line = $line." \\LARGE \\textbf{".$all_average."}"; 
                $all_users{$student}{"$sub-av"}=$all_average;
             } else {
                $line = $line." \\LARGE \\textbf{---}"; 
             }
             $line = $line."\\\\ \\hline\\hline\\pagebreak[3]\n\n";
#         } elsif ($num eq "Halbjahr"){
#             if ($divisor!=0){
#                $average_1 = $sum / $divisor;
#	     } else {
#                $average_1 = -100;
#	     }
#
#	     # save the result for later printing
#             $average_1 = &one_decimal($average_1);
#	        
#             $average_1_format = &format($average_1);
#             $sum = &format($sum);
#             $line = $line." \\textcolor{yellow}{".$sum."}";
#             if (exists $valid_marks{$average_1}){
#                $line = $line." & \\large \\textbf{".$average_1_format."}"; 
#	        $all_users{$student}{"$sub-1"}=$average_1;
#
#                # add student and its average
#                $sum_students_with_average++;
#                $sum_class=$sum_class+$average_1;
#             } else {
#                $line = $line." & \\large \\textbf{---}"; 
#	     }
#             $line = $line."\\\\ \\hline\\pagebreak[3]\n\n";
          } elsif ($num eq "Jahr"){
             if ($divisor!=0){
                $average_1 = $sum / $divisor;
	     } else {
                $average_1 = -100;
	     }
	     # save the result for later printing
             $average_1 = &one_decimal($average_1);	        

             $average_1_format = &format($average_1);
             $sum = &format($sum);
             $line = $line." \\textcolor{orange}{".$sum."}";
             if (exists $valid_marks{$average_1}){
                $line = $line." & \\large \\textbf{".$average_1_format."}"; 
       	        $all_users{$student}{"$sub-1"}=$average_1;

                # add student and its average
                $sum_students_with_average++;
                $sum_class=$sum_class+$average_1;
             } else {
                $line = $line." & \\large \\textbf{---}"; 
	     }
             $line = $line."\\\\ \\hline\\pagebreak[3]\n\n";
         } 
             print LATEX $line;
     } # end numstrings
    push @all_users , [ $student, { %marks } ];
    } # end:  foreach student


    &latex_footer($numstrings[0]);
    print LATEX "\\end{longtable}\n";
    if ($#problems > $max_problems){
       print LATEX "\\end{landscape}\n";
    }
  } # end: foreach subject


  # print overview 
  if ($exam==1){
     &print_all_results_per_user();
  } else {
     # midyear, year
     &print_all_results();
  }
  &latex_end();
  &compile_latex($result,$result,"results");
  if ($exam==1){
      &compile_latex($result,$result,"results","kammer");
  }
  # creating classlists
  &create_classlists($result,$mode);

  # cleaning up
  my $command="rm ${prefix}$result/results/${mode}/*.txt";
  print "Cleaning up ...\n";
  print "$command \n";
  
# ???? do I have to clean up now?
#system($command);
  print "... done\n";
  exit;
}










############################################################
# SUB
############################################################
sub latexize {
    my ($string) = @_;
    #$string=~s/_/\_/g;
    $string=~s/_/\\_/g;

    return $string;
}


sub create_classlists {
    my ($result,$mode) = @_;
    my $result_latex=&latexize($result);
    print "${prefix_work}$result/lists/lists-class.tex \n";
    system "mkdir -p ${prefix_work}$result/lists/${mode}";
    open (LISTS, ">${prefix_work}$result/lists/${mode}/lists-${result}.tex");

print LISTS ('
\documentclass[fleqn,a4paper,10pt]{article}
%\usepackage{ifthen}
\usepackage{multicol}
\usepackage{lscape}
\usepackage{graphicx}
\usepackage{amssymb}
\usepackage{textcomp}
\usepackage{afterpage}
\usepackage{calc}
\usepackage[T1]{fontenc}
\usepackage[');
print LISTS "$coding]{inputenc}";
print LISTS ('
\usepackage{ngerman}
\usepackage{fancybox}
\usepackage{marvosym}
\usepackage{fancyhdr}
\usepackage[dvips]{color}
%\usepackage{moreverb}
%\usepackage{twoopt}
%\usepackage{psfrag}
% ams-Befehl square ab jetzt nutzlos, da \square von SIunits neu definiert wird
%\usepackage[cdot,amssymb,thickqspace]{SIunits} 
\usepackage{longtable}
\usepackage{dcolumn}
\usepackage{amsmath}
\usepackage{lastpage}
% Satzspiegel
\setlength{\voffset}{-25.4mm}
\setlength{\hoffset}{-25.4mm}

\setlength{\textwidth}{190mm}
\setlength{\topmargin}{0mm}
\setlength{\textheight}{250mm}
\setlength{\headheight}{11mm}
\setlength{\headsep}{2mm}
\setlength{\topskip}{0mm}

\setlength{\footskip}{26.5mm}
\setlength{\parindent}{0mm}

% ohne Rand 
\setlength{\oddsidemargin}{9mm}
\setlength{\evensidemargin}{9mm}

% zentriert
%\setlength{\oddsidemargin}{15mm}
%\setlength{\evensidemargin}{15mm}

\setlength{\fboxsep}{1mm}
\setlength{\fboxrule}{0.35mm}
\setlength{\mathindent}{8mm}

%\newcounter{mypage}
%\setcounter{mypage}{1}

\pagestyle{fancy}
\newcommand{\headrotate}[1]{\makebox[3mm][c]{\begin{rotate}{60}#1\end{rotate}}}


\lhead{\large\textbf{Klassenliste}}
\chead{}
\rhead{}
\cfoot{}
%\lfoot{\thesection}%
\lfoot{Berufliches Schulzentrum Leonberg}
%\newcounter{showsectionheaders}
%\setcounter{showsectionheaders}{0}

\definecolor{red}{rgb}{1,0,0} 
\definecolor{green}{rgb}{0.15,0.75,0.15}
\definecolor{blue}{rgb}{0.2,0,1}
\definecolor{yellow}{rgb}{0.7,0.7,0.15}
\definecolor{orange}{rgb}{1,0.65,0.15}
');
    print LISTS "\\rhead{$result_latex}\n";
    print LISTS "\\rfoot{Created by \\texttt{examplix} on \\today}\n";

    print LISTS "\\chead{}\n";

    print LISTS "\\begin{document}\n";


    print LISTS "\\begin{tabular}{|r|l|p{10mm}|p{10mm}|p{10mm}|p{10mm}|p{10mm}|p{10mm}|p{40mm}|} \\\\ \\hline\n";
    print LISTS "\\rule[-2mm]{0mm}{6.8mm}\\textbf{Nr.} & Name & & & & & & & \\\\ \\hline\\hline\n\n";

    my $count=0;
    my $rule="";
    if ($#students < 32 and $#students >=29 ){
        $rule="\\rule[-1mm]{0mm}{4.8mm}";
    } elsif ($#students < 29 and $#students >=25){
        $rule="\\rule[-1.5mm]{0mm}{5.8mm}";
    } elsif ($#students < 25){
        $rule="\\rule[-2mm]{0mm}{6.8mm}";
    }

    my $student_name="";
    foreach my $student (@students){
          if (exists $student_updates{$student}){
              # mapping exists 
	      $student_name=$student_updates{$student};
          } else {
              $student_name=$student;   
          }
        $count++;
        print LISTS "$rule \\textbf{$count} & $student_name & & & & & & & \\\\ \\hline\n\n";
    }

    print LISTS "\\end{tabular} \n";


    print LISTS "\\end{document}\n";

    close(LISTS);

    &compile_latex($result,$result,"lists");
}



sub read_results_teacher {
    my %users=();
    my @users=();
    my $result_latex=&latexize($result);

    my $file_users=$prefix.$result."/sysusers.cfg";

    $pro_name=$result;
    @students=&get_students($result,$teacher);
    %hash = &create_task_hash($result,$teacher);
    print "Opening the following Result-Files of exam $result:\n";
    while (my ($file,$prob) = each %hash ){
        my ($abs_file,$teacher)=&abs_path_xls_file_teacher($file);
        print "   $file with Problems: $prob \n";
        my ($user,$subject) = split(/_/,$file);
        my $subject_short=&translate_to_short($subject);

        if (not exists $users{$user}){
            # decide if teacher exists
            my ($name)=getpwnam($user);
            if (defined $name){
                $users{$user}="seen";
            }
        }

        # teacher level
        print "My file is $file \n";
        my $basefile=$file;
        $basefile=~s/\.xls$//;

        print "My basefile is $basefile \n";
        print "My inotify  is $inotify \n";
        if ($inotify ne "" 
            and $inotify ne $basefile){
            # option is given
            # but not the changed file
            print "   NOT creating a result file for $basefile\n";
            next;

        }

        print "   CREATING a result file for $basefile\n";
        foreach my $mark_type (@mark_types){
            print "Opening $mark_type of $file\n";
            my ($abs_file,$teacher)=&abs_path_xls_file_teacher($file);
            &read_xls_file_teacher($abs_file,
                                   $prob,
                                   $mark_type,
                                   $mark_types_count{$mark_type});
        }


        # create result files *.tex(pdf) and *.txt
        #my $basefile=$file;
        #$basefile=~s/\.xls$//;

        # create txt
        open (RESULTTL, ">${prefix_work}$result/results/${mode}/${basefile}.txt");
        print RESULTTL "# Do not edit this file\n";
        print RESULTTL "# It is automatically created by examplix\n";

        # create a pdf
        open (LATEXTL, ">${prefix_work}$result/results/${mode}/results-$user-$subject.tex");
        print LATEXTL ${DevelConf::latex_preamble};

        print LATEXTL "\\chead{\\textbf{${subject}---${subject_short}}}\n";
        print LATEXTL "\\rhead{\\textbf{$user}}\n";
        print LATEXTL "\\lhead{\\textbf{$result_latex}}\n";
        print LATEXTL "\\rfoot{Created by \\texttt{examplix} on \\today}\n";

        print LATEXTL "\\newcommand{\\headrotate}[1]{\\makebox[3mm][c]{\\begin{rotate}{60}#1\\end{rotate}}}\n";
        print LATEXTL "\\begin{document}\n";

        # define the tables
        my $first_header="\\begin{longtable}{|r|l||";
        my $second_header="   \\rule{0mm}{35mm}\n& ";
        my $third_header="   & \\rule[-1.8mm]{0mm}{6mm}\\textbf{Name}\n";
        my $weighting_line="\\center{\\textbf{Gewichtung im Fach $subject:}\n   \\quad ";
     
        # counter for columns
        my $column_count=0;
        my $factor_zero_counter=0;

        foreach my $mark_type (@mark_types){
            my $factor=$metadata_teacher_level{$subject}{$teacher}{$mark_type}{'user_factor'};
            if (not defined $factor){
                $factor=0;
                $factor_zero_counter++;
            }
            if ($factor eq "user_factor"){
                $factor=0;
                $factor_zero_counter++;
            }
	    $weighting_line=$weighting_line."${mark_type}: ${factor}x \\quad ";
           my $max_col=
              $metadata_teacher_level{$subject}{$teacher}{$mark_type}{"max_columns"};
           for (my $i = 1; $i <= $max_col; $i++) {
               my $key=$mark_type.$i;
               my $user_comment=$metadata_teacher_level{$subject}{$teacher}{$mark_type}{"${mark_type}${i}"}{'user_comment'};

               $column_count++;
               $first_header=$first_header."p{5mm}";
               $second_header=$second_header."   & \\headrotate{$user_comment}\n";

               if ($i==$max_col){
                   $third_header=$third_header.
                   "   & \\multicolumn{1}{c||}{\\footnotesize{$key}}\n";
               } else {   
                   $third_header=$third_header.
                   "   & \\multicolumn{1}{c|}{\\footnotesize{$key}}\n";
               }
           } 
           if (not $max_col==0){
               # uncomment 6 lines to see sum
               #$column_count++;
               #$first_header=$first_header."p{6mm}";
               #$second_header=$second_header."   &\n";
               #$third_header=$third_header.
               #               "   & \\multicolumn{1}{c|}{\$\\Sigma_{".
               #               $mark_type."}\$}\n";

               # average
               $column_count++;
               $first_header=$first_header."p{6mm}";
               $second_header=$second_header."   &\n";
               $third_header=$third_header.
                              "   & \\multicolumn{1}{c||}{\$\\varnothing_{".
                              $mark_type."}\$}\n";
           }
        }


        # append average column
        $first_header=$first_header."p{8mm}";
        $second_header=$second_header."   &\n";
        $third_header=$third_header.
                       "   & \\multicolumn{1}{c|}{\$\\varnothing_{".
                       $subject_short."}\$}\n";


        # end the line
        $weighting_line=$weighting_line."} \n\n";
        $first_header=$first_header."|} \\hline \n";
        $second_header=$second_header."   \\\\ \\hline \n";
        $third_header=$third_header."   \\\\ \\hline \\hline \n";

        # decide if portrait or landscape
        $landscape=0;
        if ($column_count > 12){
            $landscape=1;
            print LATEXTL "\\begin{landscape}\n\n";
        }
        
        if ($factor_zero_counter==$mark_types_count){
            print LATEXTL "\\center{\\large\\textcolor{red}{Es sind keine Gewichtungen"
                         ," angegeben für $subject}}";
        } else {
            print LATEXTL $weighting_line;
        }

 
        print LATEXTL $first_header; 
        print LATEXTL $second_header; 
        print LATEXTL $third_header; 
        my @students=&get_students($result);

        my $rule="";
        if ($#students < 32 and $#students >=29 ){
            $rule="\\rule[-1mm]{0mm}{4.8mm}";
        } elsif ($#students < 29 and $#students >=25){
            $rule="\\rule[-1.5mm]{0mm}{5.8mm}";
        } elsif ($#students < 25){
            $rule="\\rule[-2mm]{0mm}{6.8mm}";
        }

        my $count=1; 
        foreach my $student (@students){
            my $student_name="";
            if (exists $student_updates{$student}){
                # mapping exists 
	        $student_name=$student_updates{$student};
            } else {
                $student_name=$student;   
            }
            print LATEXTL "\n   $count & $rule $student_name \n";
            my $total_sum=0;
            my $total_divisor=0;
            my $calc_possible=1;
            foreach my $mark_type (@mark_types){
               my $max_col=
                  $metadata_teacher_level{$subject}{$teacher}{$mark_type}{"max_columns"};
               for (my $i = 1; $i <= $max_col; $i++) {
                   my $key=$mark_type.$i;
                   my $mark=$user_teacher_level{$student}{$subject}{$mark_type}{$key};
                   my $mark_formatted=&format($mark);
                   #if (not defined $mark_formatted){
                   #    $mark_formatted="";
                   #}
                   if ($i==$max_col){
                       print LATEXTL "     & \\multicolumn{1}{c||}{$mark_formatted}\n";
                   } else {
                       print LATEXTL "     & \\multicolumn{1}{c|}{$mark_formatted}\n";
                   }
               } 
               if (not $max_col==0){
                   # there should be marks for that $mark_type
                   my $mark=$user_teacher_level{$student}{$subject}{$mark_type}{'sum'};
                   my $mark_formatted=&format($mark);
                   # uncomment 1 line to see sum
                   #print LATEXTL "     & \\multicolumn{1}{c|}{$mark_formatted}\n";
                   my $average=$user_teacher_level{$student}{$subject}{$mark_type}{'average'};
                   my $average_two_decimal= &two_decimal($average);
                   my $average_formatted=&format($average_two_decimal);
                   if ($average_formatted eq ""){
                       # show with --- that calculation was not possible
                       $average_formatted="---";
                   }
                   print LATEXTL "     & \\multicolumn{1}{c||}{$average_formatted}\n";
                   if (defined $average){
                       $total_sum=$total_sum+($average*$metadata_teacher_level{$subject}{$teacher}{$mark_type}{"user_factor"});
                   } else {
                       # marks are missing, cannot calculate
                       $calc_possible=0;
                   }
                   $total_divisor=$total_divisor+$metadata_teacher_level{$subject}{$teacher}{$mark_type}{"user_factor"};
	       }
            }

            my $total_average;
            if (not $total_divisor==0){
               $total_average=$total_sum/$total_divisor;
	    } else {
		$total_average=0;
            }

            # check if average is calculated correctly
            if ($calc_possible==1){
                $user_teacher_level{$student}{$subject}
                                   {'total_average'}=$total_average;
                my $average_two_decimal= &two_decimal($total_average);
                my $average_formatted=&format($average_two_decimal);
                print LATEXTL "     & \\multicolumn{1}{c|}{$average_formatted} ";
                # save average for class taecher level
                my $average_one_decimal= &one_decimal($total_average);
                # save it in a file            	        
                print RESULTTL $student."::".$average_one_decimal."::\n";
                # save it in a hash ???
                $user_teacher_level{$student}{$subject}
                                   {'one_decimal_average'}=$average_one_decimal;
            } else {
                # data missing, cannot calculate average correctly
                $user_teacher_level{$student}{$subject}{'total_average'}=0;
                my $average_two_decimal= &two_decimal($total_average);
                print LATEXTL "     & \\multicolumn{1}{c|}{---} ";
                print RESULTTL $student."::0::\n";
                # save it in a hash ???
                $user_teacher_level{$student}{$subject}
                                   {'one_decimal_average'}=0;
            }

            $count++;
            print LATEXTL "\\\\ \\hline ";
        }

        # add double line
        print LATEXTL " \\hline \n\n";

        # add footer line with averages
        my $first_footer="   \\rule[-1.8mm]{0mm}{6mm} & \$\\varnothing\$ ";
        foreach my $mark_type (@mark_types){
            my $factor=$metadata_teacher_level{$subject}
                       {$teacher}{$mark_type}{'user_factor'};
            if (not defined $factor){
                $factor=0;
            }
            if ($factor eq "user_factor"){
                $factor=0;
            }
           my $max_col=$metadata_teacher_level{$subject}{$teacher}
                       {$mark_type}{"max_columns"};
           for (my $i = 1; $i <= $max_col; $i++) {
               my $key=$mark_type.$i;
               my $problem_average=$metadata_teacher_level{$subject}{$teacher}
                                   {$mark_type}{$key}{"problem_average"};
               my $problem_average_formatted=&format($problem_average);
               if ($i==$max_col){
                   $first_footer=$first_footer."& \\multicolumn{1}{c||}{".
                                 $problem_average_formatted."} ";
               } else {
                   $first_footer=$first_footer."& \\multicolumn{1}{c|}{".
                   $problem_average_formatted."} ";
               }   
        } 
           if (not $max_col==0){
               # uncomment 1 line to see sum
               #$first_footer=$first_footer."& ";
               # average
               $first_footer=$first_footer."& \\multicolumn{1}{c||}{}";
           }
        }
        # append average column
        $first_footer=$first_footer."& ";

        # end the line
        $first_footer=$first_footer." \\\\ \\hline \n";

        print LATEXTL $first_footer; 

        print LATEXTL "\\end{longtable}\n";
        if ($landscape==1){
            print LATEXTL "\\end{landscape}\n\n";
        }
        print LATEXTL "\\end{document}";
        close (LATEXTL);
        close (RESULTTL);
        # compile the file
        &compile_latex("$result","$user-$subject","results");
    }
}



sub fetch_mode_not_used {
    my ($option) = @_;
    my $mode ="";
    my $exam=0;
    my $year=0;
    if (-e "$option/exam.cfg"){
	$exam=1;
        $mode="exam";
    }
    if (-e "$option/year.cfg"){
        $year=1;
        $mode="year";
    }

    if ($exam==1 and ($year==1 or $midyear==1)){
	print "\nERROR: Could not determine mode (year or exam).\n";
	print "       Delete $option/exam.cfg or \n";
	print "       Delete $option/year.cfg \n\n";
        exit;
    } elsif ($exam==0 and $year==0 and $midyear==0){
	print "\nERROR: Could not determine mode (year or exam).\n";
	print "       Create $option/exam.cfg or \n";
	print "       Create $option/year.cfg \n\n";
        exit;
    }
    print "##### Running in $mode-mode\n";
    return $mode;
}



sub read_xls_file {
    my ($file,$prob) = @_;
    my @problems = split(/;/,$prob);
    my ($teacher,$subject,$num,$day) = split(/_/,$file);

    # adding to hash problem-> corrector
    $all_correctors{$day}{$prob}{$subject}=$teacher;  
 
    my $xls_path = "${prefix_work}$result/collect/${mode}/$file";
    my $txt_path = $xls_path;
    $txt_path=~s/\.xls$//;
    $txt_path=~s/\/collect\//\/results\//;
    $txt_path=$txt_path.".txt";
    if (not -e "$result/collect"){
        system("mkdir -p ${prefix_work}$result/collect");
    }

    print "Reading $xls_path for Values: $prob \n";
    my $oBook = Spreadsheet::ParseExcel::Workbook->Parse("$xls_path");
    my($iR, $iC, $oWkS, $oWkC);
    foreach my $oWkS (@{$oBook->{Worksheet}}) {
       my $column;
       # which column to take
       if ($year_opt==1){
           $column=2;
       } elsif ($midyear_opt==1){
           $column=1;
       } elsif ($exam==1){
           $column=0;
       }
       foreach my $pro (@problems){
	  if ($exam==1){
              $column++;
	  }
          # check correct column
          my $oWkC = $oWkS->{Cells}[8][$column];
          my $header=$oWkC->Value;
          # In Zeile 6 steht Halbjahr, Schuljahr
          my $oWkC2 = $oWkS->{Cells}[5][$column];
          my $year_part=$oWkC2->Value;
          if($log_level>=3){
              print "   I try to read $pro from column with header $header ($year_part)\n";
          }
          if ($pro eq $header){
              for(my $iR = 9;
                 defined $oWkS->{MaxRow} && $iR <= $oWkS->{MaxRow} ; $iR++) {
                 # Reading the values from all students
                 my $oWkC = $oWkS->{Cells}[$iR][0];
                 my $oWkC2 = $oWkS->{Cells}[$iR][$column];
                 # faster, performance ???? lookup student just once
                 # then iterate through problems
                 my $student = $oWkC->Value;
                 my $mark = $oWkC2->Value;
		 #print "Reading Column $column: $student  --> $mark\n";

                 if ($mark eq ""){
                     $mark=-100;
                 } elsif ($mark eq "i" or $mark eq "ign" or $mark eq "ignore"){
                     $mark=-300;
                 } elsif ($mark eq "zweit" or $mark eq "ZWEIT"){
                     $mark=-2000;
                 } elsif ($mark eq "fhsr" or $mark eq "FHSR"){
                     $mark=-3000;
                 } elsif ($mark eq "hsr" or $mark eq "HSR"){
                     $mark=-4000;
                 } elsif ($mark eq "mih" or $mark eq "MIH"){
                     $mark=-5000;
                 }
                 if($log_level>=3){
                     print "   Saving: $student $teacher $subject ",
                           "$num $day $pro has mark $mark \n";
                 }
                 # add the mark to the hash
                 if ($year==1 or $midyear==1){
                     # year_part is Halbjahr, Schuljahr
                     $all_marks{$student}{$teacher}{$subject}{$year_part}{$day}{$pro}=$mark;
                 } elsif ($exam==1){
                     $all_marks{$student}{$teacher}{$subject}{$num}{$day}{$pro}=$mark;
                 }
	      } # end: for
          } else {
	      print "\nERROR: wrong Header $header for $subject\n\n";
          }
       }
    }

#    if ($year==1){
#        print "Reading $txt_path for Values: $prob \n";
#        open (TXT, "<$txt_path");
#        while (<TXT>){
#            s/^ //g; # Leerzeichen am Zeilenangfang entfernen
#            if(/^\#/ or 
#                /^\s/
#              ){ # # am Anfang bedeutet Kommentarzeile
#                  next;
#            }
#            my ($user,$average)=split(/::/);
#            # add the mark to the hash
#           $all_marks{$user}{$teacher}{$subject}{$num}{$day}{'calc_average'}=$average;
#        }
#    }
}



sub read_typeout {
   my %result=();
   open (TYPEOUT, "${prefix_work}$result/typeout.cfg") || die "Fehler: $!";
   if($log_level>=3){
      print "\nOPENING file ${prefix_work}$result/typeout.cfg\n";
   }
   while (<TYPEOUT>){
       chomp();
       my ($key,$value) = split(/\=/,$_);
       $result{$key}=$value;
   }
   return %result;
}



sub read_xls_reg_mark_file {
    my $teacher="class-teacher";
    my $file="";
    if ($exam==1){
        $file="Anmeldenoten_all.xls";
    } else {
        if ($midyear==1){
            $file="override_Halbjahr.xls";
        } elsif ($year==1){
            $file="override_Schuljahr.xls";
        }
    }
    my $path = "${prefix_work}$result/collect/${mode}/$file";
    my @problems = &get_loop_subjects();

    print "Reading $path for Values\n";
    if (not -e $path){
        print "ERROR: $path not found!\n\n";
        exit;
    }

    my $oBook = Spreadsheet::ParseExcel::Workbook->Parse("$path");
    my($iR, $iC, $oWkS, $oWkC);
    foreach my $oWkS (@{$oBook->{Worksheet}}) {
       my $column=0;
       foreach my $pro (@problems){
          my $subject_short=&translate_to_short($pro);
           if (exists $examonly_subject{$subject_short}){
                 # no Anmeldenoten needed
	         print "   INFO: No registration mark needed ",
                       "for $pro (EXAMONLY_SUBJECT)\n";
                 next;
           }
          # check correct column
          $column++;
          my $line=8;
          my $oWkC = $oWkS->{Cells}[$line][$column];
          my $header=$oWkC->Value;
          if($log_level>=3){
              print "   I try to read $pro ($subject_short) ".
                    "from column $column and line $line with header $header \n";
          }
          if ($subject_short eq $header){
              # Reading the values
              for(my $iR = 9;
                 defined $oWkS->{MaxRow} && $iR <= $oWkS->{MaxRow} ; $iR++) {
                 my $oWkC = $oWkS->{Cells}[$iR][0];
                 my $oWkC2 = $oWkS->{Cells}[$iR][$column];
                 my $student = $oWkC->Value;
                 my $mark = $oWkC2->Value;
                 if ($mark eq ""){
                     $mark=-100;
                 } elsif ($mark eq "i" or $mark eq "ign" or $mark eq "ignore"){
                     $mark=-300;
                 } elsif ($mark eq "zweit" or $mark eq "ZWEIT"){
                     $mark=-2000;
                 } elsif ($mark eq "fhsr" or $mark eq "FHSR"){
                     $mark=-3000;
                 } elsif ($mark eq "hsr" or $mark eq "HSR"){
                     $mark=-4000;
                 } elsif ($mark eq "mih" or $mark eq "MIH"){
                     $mark=-5000;
                 }
                 if($log_level>=3){
                     print "     * Saving: $student $teacher",
                           " $subject_short $mark \n";
                 }
                 # push the mark in the hash
 	         $reg_marks{$student}{$teacher}{$subject_short}=$mark;
	      }
          } else {
	      print "\nERROR: wrong Header for $subject_short\n\n";
          }
       }
    }
}



sub print_all_results_per_user {
   print LATEX "\\newpage \n\n";
   #command for the area under the name for tickmarks
   print LATEX '
\newcommand{\finres}[1]{%
\setlength{\unitlength}{1mm}
\begin{picture}(0,0)
  % frame for final result
  \put(32,0){\framebox(10,6){#1}}
  \put(28,2.2){$\varnothing$} %or use \O{}
  % tickboxes
  \put(-2,0){\framebox(4,4){}}
  \put(3.5,1){\footnotesize Preis}
  \put(-2,5){\framebox(4,4){}}
  \put(3.5,6){\footnotesize Auszeichnung}
  \put(-2,10){\framebox(4,4){}}
  \put(3.5,11){\footnotesize Belobigung}
  \put(-2,15){\framebox(4,4){}}
  \put(3.5,16){\footnotesize Schulpr{\"u}fung bestanden}
  %\put(0,5){\line(1,0){60}}
  %\put(57,0){\makebox(0,10)[b]{#1}}
\end{picture} \hfill
}
';


# is always exam ???
   if ($mode eq "exam"){
       print LATEX "\\section{Pr{\\\"u}fungs-Notenliste}\n\n";
   } elsif ($mode eq "year"){
       print LATEX "\\section{Zeugnis-Notenliste ($latex_title)}\n\n";
   }

   my @students=&get_students($result);   
   my $i=0;

   # calculate span of \cline
   my $from=3;
   my $to=$#final_subjects_show+4;

   # class of first student
   print KAMMER "\n\\begin{center}\n\n".
                "  \\vspace*{4mm}\n\n".
                "  \\textbf{\\Large $students_class{$students[0]}}\n\n".
                "  \\vspace*{6mm}\n\n";
   # create the kammer table header
   my $kammer_table_header=
      "  \\begin{tabular}{|r|l||c|c||c|c|} \\hline \n".
      "    \\rule[-2mm]{0mm}{7mm}    &                & WSK  & WSK    & KKT  & KKT \\\\\n".
      "    \\rule[-2mm]{0mm}{5mm}\\textbf{Nr.} ".
      "& \\textbf{Name} & Note & Punkte & Note & Punkte".
      " \\\\\\hline\\hline\n";
   print KAMMER "$kammer_table_header";
   # create the table header 
   my $latex_table_header="\\begin{tabular}{|p{6mm}|p{36mm}|c|";
   foreach my $subject (@final_subjects_show){
      $latex_table_header=$latex_table_header."p{15mm}|";
   }
   $latex_table_header=$latex_table_header."p{40mm}|} \\hline \n";

   # create the first line with headings
   my $span=$#final_subjects_show+4;
   my $first_line_suffix=" \\\\  \n";

   # create the second line with headings
   my $second_line_suffix="& & ";
   foreach my $subject (@final_subjects_show){
      my $subject_short=&translate_to_short($subject);
       $second_line_suffix=$second_line_suffix.
          "  \\multicolumn{1}{c|}{$subject_short} & \n";
   }
   $second_line_suffix=$second_line_suffix.
        "  \\multicolumn{1}{l|}{Bemerkungen} \\\\  \\hline \\hline\n";

   my @extensions=();
   if (defined $numstrings[2]){
       if ($numstrings[2] eq "Drittkorrektur"){
         @extensions=("-1","-2","-3","-av");
       } else {
	   print "ERROR: $numstrings[2] \n";
           exit;
       } 
   } else {
      @extensions=("-1","-2","-av"); 
   }

   my $last_class="";

   foreach my $student (@students){
      my $student_name="";
      if (exists $student_updates{$student}){
          # mapping exists 
	  $student_name=$student_updates{$student};
      } else {
          $student_name=$student;   
      }

      if($log_level>=2){
          print "\nWorking out result table of $student_name\n";
      }

      # check if it's a dummy student (last name = class)
      # class of student ?????????
      my $this_class=$students_class{$student};
      my ($last,$first)=split(/,/,$student_name);
      #print "Last: $last First: $first    in $this_class\n";
      if ($last eq $this_class){
          # a dummy user
          next;
      }

      my @school_final_marks=(); # list of marks relevant for average
      my $not_taken_comment="";
      $i++;


      if ($this_class ne $last_class){
          # results
          if ($last_class ne ""){
              print LATEX "\\newpage\n\n";
          }
          print LATEX "\\lhead{Klasse: $this_class}\n";
          print LATEX "\\section*{Klasse: $this_class}\n";
      }
    
      if ($this_class ne $last_class and $last_class ne ""){
          # kammer
          if ($last_class ne ""){
              print KAMMER "  \\end{tabular}\n\\end{center}\n\n";
          }
          print KAMMER "\\newpage\n\n";
          print KAMMER "\n\\begin{center}\n\n".
	               "  \\vspace*{4mm}\n\n".
                       "  \\textbf{\\Large $this_class}\n\n".
	               "  \\vspace*{6mm}\n\n";
          print KAMMER "$kammer_table_header";
      }


      $last_class=$this_class;

      print LATEX "$latex_table_header";


      print LATEX "\\multicolumn{1}{|r|}{",
                  "\\rule[-1mm]{0mm}{5.5mm}\\textbf{$i}} ",
                  "& \\multicolumn{$span}{l|}{",
                  "\\textbf{$student_name}$students{$student}} ";
      print LATEX "$first_line_suffix";


      print LATEX "\\multicolumn{1}{|r|}{\\rule[-1.5mm]{0mm}{2mm}} &\n";
      print LATEX "$second_line_suffix";

      # Anmeldenoten
      print LATEX "\\multicolumn{2}{|l|}{} & Anmeld. &\n";
      foreach my $subject (@final_subjects_show){
         my $teacher="class-teacher";
         my $subject_short=&translate_to_short($subject);

         # if show subject, leave empty
         if ($subject_type{$subject_short} eq "SHOW_SUBJECT"){
             print LATEX "  \\multicolumn{1}{c|}{} &\n";
             next;
         }         

         my $mark=$reg_marks{$student}{$teacher}{$subject_short};
         my $string="";
         if (not defined $mark or $mark eq ""){
     	    $mark="---";
         } elsif ($mark<-1000) {
	     $string="\\textcolor{blue}{$not_taken_string}";
         } elsif ($mark==-100) {
	     $string="\\colorbox{blue}{---}";
         } else {
            $mark = &format($mark,"integer");
            $string="\\textcolor{blue}{$mark}";
         }
         if($log_level>=3){
             print "  $student($subject_short): ",
                   "Registration Mark is ${mark}\n";
         }
         print LATEX "  \\multicolumn{1}{c|}{$string} &\n";
      }
      print LATEX "\\\\  \\cline{$from-$to} \n";

      foreach my $ext (@extensions){
         print LATEX "\\multicolumn{2}{|l|}{}  & Pr{\\\"u}f$ext &\n";

         # results of exam
         foreach my $subject (@final_subjects_show){
	    my $string=$subject.$ext;
            my $subject_short=&translate_to_short($subject);

            # if show subject, leave empty
            if ($subject_type{$subject_short} eq "SHOW_SUBJECT" or
                $subject_type{$subject_short} eq "LOOP_SUBJECT" or
                $subject_type{$subject_short} eq "EXTRA_SUBJECT" or
                $subject_type{$subject_short} eq "EXAMONLY_SUBJECT" ){
                print LATEX " \\multicolumn{1}{c|}{} & ";
                next;
            }         

            my $mark=$all_users{$student}{$string};
            if (not defined $mark or $mark eq ""){
		$mark="---";
            } else {
                $mark = &format($mark);
            }
            if ($ext eq "-1"){
                print LATEX "  \\multicolumn{1}{c|}{\\textcolor{green}{$mark}}  &\n";
            } elsif ($ext eq "-2"){
                print LATEX "  \\multicolumn{1}{c|}{\\textcolor{green}{$mark}}  &\n";
            } elsif ($ext eq "-3"){
                print LATEX "  \\multicolumn{1}{c|}{\\textcolor{green}{$mark}}  &\n";
            } elsif ($ext eq "-av"){
                print LATEX "  \\multicolumn{1}{c|}{\\textcolor{green}{$mark}}  &\n";     
            }
         }
         print LATEX "\n\\\\  \\cline{$from-$to} \n";
      }

      # Endnote
      my $end_line="";
      foreach my $subject (@final_subjects_show){
          my $reg_mark;
          my $subject_short=&translate_to_short($subject);
          if($log_level>=2){
              print "  SUB: $subject ($subject_short),",
                    " Type $subject_type{$subject_short}\n";
          }
 
          # if show subject, leave empty
          if ($subject_type{$subject_short} eq "SHOW_SUBJECT"){
              $end_line=$end_line."  \\multicolumn{1}{c|}{} &\n";
              next;
          }         

          # if examonly subject, ...
          if ($subject_type{$subject_short} eq "EXAMONLY_SUBJECT"){
              $end_line=$end_line."  \\multicolumn{1}{c|}{-AA-} &\n";
              next;
          }         
          # if LOOP_SUBJECT, print reg_mark
          # if EXTRA_SUBJECT, print reg_mark, ignore it in @school_final_marks (not part of average)
          if ($subject_type{$subject_short} eq "LOOP_SUBJECT" or
              $subject_type{$subject_short} eq "EXTRA_SUBJECT"){
              $reg_mark=$reg_marks{$student}{"class-teacher"}{$subject_short};

              if ($subject_type{$subject_short} eq "EXTRA_SUBJECT"){
                  # not part of average
              } else {
                  # save it for school average
                  push @school_final_marks, $reg_mark;
              }

              if (not defined $reg_mark or $reg_mark==-100){
                  $end_line=$end_line.
                  "  \\multicolumn{1}{c|}{\\colorbox{red}{---}} &\n";
              } elsif ($reg_mark==-2000 or 
                       $reg_mark==-3000 or 
                       $reg_mark==-4000 or
                       $reg_mark==-5000 ){
                  $end_line=$end_line.
                  "  \\multicolumn{1}{c|}{\\textcolor{red}{$not_taken_string}} &\n";
	      } else {
                  $end_line=$end_line.
                  "  \\multicolumn{1}{c|}{\\textcolor{red}{$reg_mark}} &\n";
	      }
              next;
          }         

          # calculating result (exam and reg_mark) when subject is MAIN
          my $exam=$reg_marks{$student}{"exam"}{$subject_short};

          $reg_mark=$reg_marks{$student}{"class-teacher"}{$subject_short};

          # check if defined
          if (not defined $exam){
              $exam=-100;
              print "    WARNING: No exam mark ",
                    "for $student in $subject_short found\n";
          }
          if (not defined $reg_mark){
              $reg_mark=-100;
              if (not exists $examonly_subject{$subject_short}){
                  print "    WARNING: No registration mark ",
                        "for $student in $subject_short found\n";
              }
          } 

          if($log_level>=2){
   	      print "      $student_name: >$reg_mark< in $subject_short \n";
          }
          # overwrite school_exam if correct calculation is not possible
          if ($reg_mark<-1000){
	      $not_taken_comment=$not_taken_comments{$reg_mark};
             $end_line=$end_line.
                "  \\multicolumn{1}{c|}{\\textcolor{red}{$not_taken_string}} &\n";
          } elsif ($reg_mark==-100 and 
                   exists $examonly_subject{$subject_short}){
	        if ($exam==-100){
                   # no exam average mark
   		   my $exam_form=&format($exam);
                   if (exists $examonly_subject_references{$subject_short}){
                       # exam in referenced subject not taken
                       my $display="-Y-";
                       # check referenced subject
                       my $reference_mark=$reg_marks{$student}{"class-teacher"}{$examonly_subject_references{$subject_short}};
                       if ($reference_mark==-2000 or 
                           $reference_mark==-3000 or 
                           $reference_mark==-4000 or
                           $reference_mark==-5000){
                            # referenced subject was not taken --> show $not_taken_string
                            $end_line=$end_line.
                            "  \\multicolumn{1}{c|}{\\textcolor{red}{$not_taken_string}} &\n";
                       } elsif ($reference_mark==-100){
                            # referenced subject is empty --> show ---
                            $end_line=$end_line.
                            "  \\multicolumn{1}{c|}{\\textcolor{red}{---}} &\n";
                       } else {
                            # referenced subject has a mark --> show Missing result --- 
                            # (exam should have been taken)
                            $end_line=$end_line.
                            "  \\multicolumn{1}{c|}{\\colorbox{red}{---}} &\n";
                       }
                   } else {
                       # exam not taken
                       $end_line=$end_line.
                        "  \\multicolumn{1}{c|}{\\colorbox{red}{---}} &\n";
                   }
                  } else {
                   # repeat exam average mark
                   push @school_final_marks, $exam;
                   # save kammer marks
                   $kammer_marks{$student}{$subject_short}=$exam;      
		   my $exam_form=&format($exam);
                   $end_line=$end_line.
                    "  \\multicolumn{1}{c|}{\\textcolor{red}{$exam_form}} &\n";
                }
          } elsif ($exam==-100 or $reg_mark==-100){
                # no calculation possible
                $end_line=$end_line.
                   "  \\multicolumn{1}{c|}{\\colorbox{red}{---}} &\n";
	  } else {
             my $school_exam=($exam_factor*$exam+$reg_mark_factor*$reg_mark)/3;
                $school_exam = &final_mark($school_exam);
                $school_exam = &format($school_exam,"integer");
             # save it for calculating all average
             push @school_final_marks, $school_exam;
             $reg_marks{$student}{"schoolexam"}{$subject_short}=$school_exam;
             $end_line=$end_line.
                "  \\multicolumn{1}{c|}{\\textcolor{red}{$school_exam}} &\n";
	  }
      }

      # calculate average of all marks
      my $school_exam_mark=0; # the average
      my $school_exam_sum=0;  # sum of relevant marks
      my $school_exam_mark_number=0; # number of marks for devision
      foreach my $mark (@school_final_marks){
	  if (not defined $mark){
              $mark=-100;
          }
          if (exists $valid_marks{$mark}){
              $school_exam_sum=$school_exam_sum+$mark;
              $school_exam_mark_number++;
          }
      }
      if ($school_exam_mark_number!=0){
          $school_exam_mark=$school_exam_sum/$school_exam_mark_number;
          $school_exam_mark= &one_decimal($school_exam_mark);	        
          $school_exam_mark= &format($school_exam_mark);
          $school_exam_mark="\\textcolor{red}{\\large $school_exam_mark}";
      } else {
          $school_exam_mark="\\colorbox{red}{\\large ---}";
      }

      # prepend stuff to final line and finish the line
      $end_line="\\multicolumn{2}{|l|}{\\finres{$school_exam_mark}} ".
                "& Zeugnis &\n".
                $end_line.
                " \\multicolumn{1}{l|}{$not_taken_comment} \\\\  \\hline \n";
 
      print LATEX "$end_line";
 
      print LATEX "\\end{tabular}\n\n";
      print LATEX "\\bigskip \n\n";

      # kammer result
       my $wsk_pts=&mark_2_points($kammer_marks{$student}{'WSK'});
       my $kkt_pts=&mark_2_points($kammer_marks{$student}{'KKT'});
       my $wsk=&format($kammer_marks{$student}{'WSK'});
       my $kkt=&format($kammer_marks{$student}{'KKT'});
       print KAMMER "  \\rule[-2mm]{0mm}{7mm}\\textbf{$i}&".
                    "\\textbf{$student_name} & ".
                    "$wsk & ".
                    "$wsk_pts & ".
                    "$kkt & ".
                    "$kkt_pts \\\\ \\hline\n";
      print KAMMERCSV $i.";".$last.";".$first.";".
                      $wsk.";".$wsk_pts.";".$kkt.";".$kkt_pts.";".
                      $this_class.";\n";
  }
  print KAMMER "\\end{tabular}\n\\end{center}\n\n";
}



# perhaps not necessary anymore
sub print_all_results{
   # print the marklist for all subjects and all students 
   # at the end of the document
   print LATEX "\\newpage \n\n";
   if ($mode eq "exam"){
       print LATEX "\\section{Pr{\\\"u}fungs-Notenliste}\n\n";
   } elsif ($mode eq "year"){
       print LATEX "\\section{Zeugnis-Notenliste ($latex_title)}\n\n";
   }

   print LATEX "\\begin{longtable}{|r|l||";

   if ($mode eq "exam"){
        # Verhalten und Mitarbeit
       print LATEX "c|c|";
   } elsif ($mode eq "year"){
        # Verhalten und Mitarbeit
       print LATEX "p{8mm}|p{8mm}||";
   } 

   foreach my $subject (@final_subjects){
      print LATEX "p{25mm}|";
   }
   print LATEX "l|} \\hline \n";
   print LATEX "\\rule[-3mm]{0mm}{9mm}Nr. & Name & ";

   if ($mode eq "exam"){
       # Verhalten und Mitarbeit
       print LATEX "& ";
   } elsif ($mode eq "year"){
       print LATEX " \\multicolumn{1}{c|}{V} & \\multicolumn{1}{c||}{M} &";
   }

   foreach my $subject (@final_subjects){
      my $subject_short=&translate_to_short($subject);
       print LATEX " \\multicolumn{1}{c|}{$subject_short} & ";
   }
   print LATEX " \\multicolumn{1}{c|}{Bemerkungen} \\\\  \\hline \\hline\n";
   &print_all_results_year();
   print LATEX "\\end{longtable}\n";
   &print_legend_line();
}


sub print_legend_line {
   print LATEX "\nErl{\"a}uterungen:\\colorbox{red}{---}: keine Note ermittelbar, ",
               "\\textcolor{green}{Note}: zwischen 2 Noten, ",
               "\\textcolor{red}{Note}: nicht ausreichend, ",
               "\\textcolor{blue}{Note}: von Hand abge{\"a}ndert";
}


# perhaps not necessary anymore
sub print_all_results_exam {
   # create output for exam
#   my @extensions=("-1","-2","-av"); 
   my @extensions=();
#   if ($numstrings[2] eq "Drittkorrektur"){
   if (defined $numstrings[2]){
       if ($numstrings[2] eq "Drittkorrektur"){
         @extensions=("-1","-2","-3","-av");
       } else {
	   print "ERROR: $numstrings[2] \n";
           exit;
       } 
   } else {
      @extensions=("-1","-2","-av"); 
   }
   my @students=&get_students($result);
   my $i=0; 
   foreach my $student (@students){
    my $student_name="";
      if (exists $student_updates{$student}){
          # mapping exists 
	  $student_name=$student_updates{$student};
      } else {
          $student_name=$student;   
      }
      $i++;
      foreach my $ext (@extensions){
         if ($ext eq "-1"){
            print LATEX "$i  & $student_name & Prüf$ext & ";
	 } else {
            print LATEX " & & Prüf$ext & ";
	 }
         foreach my $subject (@final_subjects){
	    my $string=$subject.$ext;
            my $mark=$all_users{$student}{$string};
            if (not defined $mark or $mark eq ""){
		$mark="---";
            } else {
                $mark = &format($mark);
            }
            if ($ext eq "-1"){
                print LATEX " \\multicolumn{1}{c|}{\\textcolor{red}{$mark}}  & ";
            } elsif ($ext eq "-2"){
                print LATEX " \\multicolumn{1}{c|}{\\textcolor{green}{$mark}}  & ";
            } elsif ($ext eq "-3"){
                print LATEX " \\multicolumn{1}{c|}{\\textcolor{blue}{$mark}}  & ";
            } elsif ($ext eq "-av"){
                print LATEX " \\multicolumn{1}{c|}{$mark}  & ";     
            }
         }
         if ($ext eq "-av"){
            print LATEX "\\\\  \\hline \\hline\n";
         } else {
            print LATEX "\\\\  \\hline \n";
         }
      }
   }

}



sub print_all_results_year {
   # create output for exam
   my $ext="-1";
   my @students=&get_students($result);
   my $i=0; 
   foreach my $student (@students){
         my $not_taken_comment="";
         $i++;

         my $student_name="";
         if (exists $student_updates{$student}){
             # mapping exists 
	     $student_name=$student_updates{$student};
         } else {
             $student_name=$student;   
         }

         print LATEX "$i \\rule[-2.3mm]{0mm}{7.1mm} & $student_name &";
         if ($year==1){
             print LATEX " & &";
         } elsif ($midyear==1){
             print LATEX " \\multicolumn{1}{c|}{\\,---\\,} & \\multicolumn{1}{c||}{\\,---\\,} &";
         }
         foreach my $subject (@final_subjects){          
            my $subject_short=&translate_to_short($subject);
	    my $string=$subject.$ext;
            my $mark=$all_users{$student}{$string};
            #print "Student: $student \n";
            #print "String:  $string \n";
            #print "Mark:    $mark \n";
            my $final_mark;
            my $final_mark_colored;
            my $override_mark=
               $reg_marks{$student}{"class-teacher"}{$subject_short};

            if (not defined $mark or $mark eq "" or $mark==0){
                if ($override_mark<-1000){
   		    $not_taken_comment=$not_taken_comments{$override_mark};
  		    $mark="";
                    $final_mark="---";
                    $final_mark_colored="\\normalsize *)";
                } else {
                    #print "Resetting Mark \n";
  		    $mark="";
                    $final_mark="---";
                    $final_mark_colored="\\colorbox{red}{---}";
                }
            } elsif ($mark==-100){
                if (not defined $override_mark){
                   $mark="";
                   $final_mark="---";
                   $final_mark_colored="\\colorbox{red}{---}";
	        } else {
                   $mark="";
                   $final_mark="---";
                   $final_mark_colored="\\colorbox{red}{---}";
	        }
            } elsif ($mark<0){
                $mark="";
                $final_mark="---";
                $final_mark_colored="-p-";
            } else {
                $final_mark=&final_mark($mark);
                # colorize marks
                if ($final_mark==5 or $final_mark==6){
		    $final_mark_colored="\\textcolor{red}{".$final_mark."}";
                } elsif ($mark==1.5 or $mark eq "1.5"
                      or $mark==2.5 or $mark eq "2.5"
                      or $mark==3.5 or $mark eq "3.5"
                      or $mark==4.5 or $mark eq "4.5"
                      or $mark==5.5 or $mark eq "5.5"){
		    $final_mark_colored="\\textcolor{green}{".$final_mark."}";
                } else {
                    $final_mark_colored = $final_mark;
                }
                $mark = &format($mark);
            }
  
            # use overrride mark if given
            if (defined $override_mark){
                if (exists $valid_override_marks{$override_mark}){
                    $mark = &format($mark);
                    $final_mark=$override_mark;
                    $final_mark_colored="\\textcolor{blue}{$override_mark}";
                }
	    }

            # math mode
            print LATEX "\n \\multicolumn{1}{c|}{",
                        "\\textbf{\\Large\\rule{1mm}{0mm}",
                        "\\hspace{-1.4mm}${final_mark_colored}}",
                        "\\raisebox{-1mm}{\\tiny ${mark}}",
                        "} & ";
         }
         print LATEX "\n \\footnotesize $not_taken_comment \\\\  \\hline \n";
   }

}





sub format {
    # if $type is "integer", do not append ,0
    my ($number,$type) = @_;
    if (not defined $type){
        $type="";
    }
    if (not defined $number){
        $number="";
        return $number;
    }
    if ($number eq "---"){
        return $number;
    }
    if ($number eq ""){
        # do nothing
    } else {
       # replace dots with commas
       $number =~ s/\./,/;
       if ($type eq "integer"){
           if (exists $valid_final_marks{$number}){
               $number=$valid_final_marks{$number};
           }
       }
       # append ,0 again, when necessary
       if (not $number =~ m/,/ and $type ne "integer"){
          $number = $number.",0"
       }
    }
    return $number;
}


sub dot_to_comma {
    # replace dot with comma
    my ($number) = @_;
    $number =~ s/\./,/;
    return $number;
}


sub get_all_subjects {
    my @sub = &get_subjects("all");
    return @sub;
}

sub get_loop_subjects {
    # all subjects + loop
    my @sub = &get_subjects("loop");
    return @sub;
}

sub get_show_subjects {
    my ($return) = @_;
    # all subjects + loop + show
    if (not defined $return){
        $return="array";
    }
    if ($return eq "array"){
        my @sub = &get_subjects("show");
        return @sub;
    } elsif ($return eq "hash"){
        my @sub = &get_subjects("show","hash");
        return @sub;
    }
}


sub get_days {
   my %days=();
   my @days=();
   open (CONF, "<${prefix_work}$result/${mode}.cfg") || 
           die "ERROR: ${prefix_work}$result/${mode}.cfg not found!";
   while (<CONF>){
      s/^ //g; # Leerzeichen am Zeilenangfang entfernen
      if(/^\#/ or 
         /^\s/ or
         /^SHOW_SUBJECT/ or
         /^EXAMONLY_SUBJECT/ or
         /^LOOP_SUBJECT/ or 
         /^EXTRA_SUBJECT/ 
        ){ # # am Anfang bedeutet Kommentarzeile
          next;
      }
      chomp();
      my ($day)=split(/;/);

      # days
      if (not exists $days{$day}){
          $days{$day}=1;
          # add to list if seen once
          if ($mode eq "exam"){
             push @days, $day;
          }
      }
   }
   my $string=join(",",@days);
   print "Days: $string\n";
   return @days;
}


sub get_subjects {
   my ($range,$return) = @_;
   if (not defined $return){
       $return="array";
   }
   my $loop=0;
   my $show=0;
   if ($range eq "loop"){
       # show all subjects
       $range="all";
       # show loop subjects
       $loop=1;
   }

   if ($range eq "show"){
       # show all subjects
       $range="all";
       # show loop subjects
       $loop=1;
       # show show subjects
       $show=1;
   }

   $range="" if not defined $range;
   my %subjects=();
   my %sub=(); # for return
   my @sub=();
   open (CONF, "<${prefix_work}$pro_name/${mode}.cfg") 
      || die "\nERROR: ${prefix_work}$pro_name/${mode}.cfg not found.\n\n";
   while (<CONF>){
      s/^ //g; # Leerzeichen am Zeilenangfang entfernen
      if(/^\#/ or 
         /^\s/ 
        ){ # # am Anfang bedeutet Kommentarzeile
          next;
      }
      chomp();
      if (/^LOOP_SUBJECT/){
          if ($loop==1){
              if ( $_=~m/^LOOP_SUBJECT=\"([A-Za-z_-]+)\"/ ){
                  print "   $1 found as LOOP_SUBJECT\n";
                  push @sub, $1;
                  my $short=&translate_to_short($1);
                  $sub{$short}="LOOP_SUBJECT";
	      }
          }
	  next;
      }
      if (/^EXTRA_SUBJECT/){
          if ($loop==1){
              if ( $_=~m/^EXTRA_SUBJECT=\"([A-Za-z_-]+)\"/ ){
                  print "   $1 found as EXTRA_SUBJECT\n";
                  push @sub, $1;
                  my $short=&translate_to_short($1);
                  $sub{$short}="EXTRA_SUBJECT";
	      }
          }
	  next;
      }
      if (/^SHOW_SUBJECT/){
          if ($show==1){
              if ( $_=~m/^SHOW_SUBJECT=\"([A-Za-z_-]+)\"/ ){
                  print "   $1 found as SHOW_SUBJECT\n";
                  push @sub, $1;
                  my $short=&translate_to_short($1);
                  $sub{$short}="SHOW_SUBJECT";
	      }
          }
	  next;
      }
      if(/^EXAMONLY_SUBJECT/){
          print "$_";
          if ( $_=~m/^EXAMONLY_SUBJECT=\"([A-Za-z_-]+)\"=\"([A-Za-z_-]+)\"/ ){
              # EXAMONLY_SUBJECT="WSK"="WK"
              print "   $1 found as EXAMONLY_SUBJECT\n";
              print "   $2 found as refering EXAMONLY_SUBJECT\n";
              $examonly_subject_references{$1}="$2";
              #push @sub, $1;
              my $short=&translate_to_short($1);
              # NOT adding to subjects, will be followed
              # by lines to create marks
              $sub{$short}="EXAMONLY_SUBJECT";
              $examonly_subject{$short}="seen";
          } elsif ( $_=~m/^EXAMONLY_SUBJECT=\"([A-Za-z_-]+)\"/ ){
              print "   $1 found as EXAMONLY_SUBJECT\n";
              #push @sub, $1;
              my $short=&translate_to_short($1);
              # NOT adding to subjects, will be followed
              # by lines to create marks
              $sub{$short}="EXAMONLY_SUBJECT";
              $examonly_subject{$short}="seen";
          } else {
              print "   ERROR: Could not read EXAMONLY_SUBJECT\n";
              exit;
          }
	  next;
      }
      my ($day,
          $problem,
          $subject,
          $factor,
          $corr_1,
          $group_1,
          $corr_2,
          $group_2)=split(/;/);

      # subjects
      if (not exists $subjects{$subject}){
          $subjects{$subject}=1;
          # add to list if seen once
          if ($mode eq "exam" or $range eq "all"){
             push @sub, $subject;
             $subject=&translate_to_short($subject);
             $sub{$subject}="MAIN";
          }
      } else {
	  my $old=$subjects{$subject};
          my $new=$old+1;
          $subjects{$subject}=$new;
          # add to list if seen twice 
          if ( $mode eq "year" and $old==2 and $range ne "all"){
              push @sub, $subject;
              $subject=&translate_to_short($subject);
              $sub{$subject}="MAIN";
          }
      }
   }

   if($log_level>=3){
      while (my ($sub,$count) = each %subjects ){
          print "   $sub was seen $count times\n";
      }
   }
   my $string=join(",",@sub);
   if($log_level>=3){
      print "Subjects: $string\n";
   }
   if ($return eq "array"){
       return @sub;
   } elsif ($return eq "hash"){
       return %sub;
   } else {
       print "ERROR: get_subjects called with wrong option \n";
   }
}




sub set_data_for_subject {
   my ($subject_to_fetch) = @_;
   my %seen=();
   my $seen="";
   @problems=();
   @days=();
   @factors=();

   open (CONF, "${prefix_work}$result/${mode}.cfg") || die "Fehler: $!";
   while (<CONF>){
       s/^ //g; # Leerzeichen am Zeilenangfang entfernen
       if(/^\#/ or 
          /^\s/ or 
          /^SHOW_SUBJECT/ or
          /^EXAMONLY_SUBJECT/ or
          /^LOOP_SUBJECT/ or
          /^EXTRA_SUBJECT/ 
         ){ # # am Anfang bedeutet Kommentarzeile
         next;
       }
      chomp();
      my ($day,
          $problem,
          $subject,
          $factor,
          $corr_1,
          $group_1,
          $corr_2,
          $group_2)=split(/;/);

      if ($subject eq $subject_to_fetch){
	  $seen = $day.":::".$problem;
          if (exists $seen{$seen}){
	      print "\n\nERROR:\n";
	      print "   I have seen $problem at $day in $subject \n\n";
              exit;
          } else {
              $seen{$seen} = "seen";
              push @problems, $problem;    
              push @days, $day;    
              push @factors, $factor;
          }
      }
   }
   print "Problems: ", @problems,"\n";
   print "Days    : ", @days,"\n";
   print "Factors:  ", @factors,"\n";
}



sub create_lists_header {
my ($class)=@_;
print LATEX ('
\begin{longtable}{|p{3mm}|p{31mm}||p{7mm}|p{5,4mm}|p{5,4mm}|p{5,4mm}|p{5,4mm}|p{5,4mm}|p{5,4mm}|p{5,4mm}|p{5,4mm}|p{5,4mm}|p{5,4mm}||p{7mm}|p{7mm}||p{7mm}|}\caption{Pr{\"u}fungskorrektur-Liste}\\\\ \hline 
\rule[-2mm]{0mm}{7mm} & 
  &\multicolumn{1}{c|}{\scriptsize\textcolor{red}{\!\!Pr{\"u}f.\,1\!\!}} 
  & & & & & & & & & &
  &\multicolumn{1}{c|}{\scriptsize\textcolor{red}{\!\!Pkte.\,1\!\!}} 
  &\multicolumn{1}{c||}{\scriptsize\textcolor{red}{\!\!Note\,1\!\!}} 
  & \\\\ \nopagebreak \cline{3-15}

\rule[-2mm]{0mm}{7mm} & \textbf{Name}
  &\multicolumn{1}{c|}{\scriptsize\textcolor{green}{\!\!Pr{\"u}f.\,2\!\!}}
  & & & & & & & & & &
  &\multicolumn{1}{c|}{\scriptsize\textcolor{green}{\!\!Pkte.\,2\!\!}}
  &\multicolumn{1}{c||}{\scriptsize\textcolor{green}{\!\!Note\,2\!\!}} 
  &\multicolumn{1}{c|}{\raisebox{1mm}{\!\!$\varnothing$-Note}\!\!} \\\\ \hline \hline 
\endhead 

');
}

sub create_lists {
  my ($create_lists) = @_;
  my @stud_res=&get_students($create_lists);

    open (LATEX, ">${prefix_work}${create_lists}/lists/correction.tex");
print LATEX ('
\documentclass[fleqn,a4paper,10pt]{article}
%\usepackage{ifthen}
\usepackage{multicol}
\usepackage{lscape}
\usepackage{graphicx}
\usepackage{amssymb}
\usepackage{textcomp}
\usepackage{afterpage}
\usepackage{calc}
\usepackage[T1]{fontenc}
\usepackage[');
print LATEX "$coding]{inputenc}";
print LATEX ('
\usepackage{ngerman}
\usepackage{fancybox}
\usepackage{marvosym}
\usepackage{fancyhdr}
\usepackage[dvips]{color}
%\usepackage{moreverb}
%\usepackage{twoopt}
%\usepackage{psfrag}
% ams-Befehl square ab jetzt nutzlos, da \square von SIunits neu definiert wird
%\usepackage[cdot,amssymb,thickqspace]{SIunits} 
\usepackage{longtable}
\usepackage{dcolumn}
\usepackage{amsmath}
\usepackage{lastpage}
% Satzspiegel
\setlength{\voffset}{-25.4mm}
\setlength{\hoffset}{-25.4mm}

\setlength{\textwidth}{190mm}
\setlength{\topmargin}{0mm}
\setlength{\textheight}{250mm}
\setlength{\headheight}{11mm}
\setlength{\headsep}{2mm}
\setlength{\topskip}{0mm}

\setlength{\footskip}{26.5mm}
\setlength{\parindent}{0mm}

% ohne Rand 
\setlength{\oddsidemargin}{9mm}
\setlength{\evensidemargin}{9mm}

% zentriert
%\setlength{\oddsidemargin}{15mm}
%\setlength{\evensidemargin}{15mm}

\setlength{\fboxsep}{1mm}
\setlength{\fboxrule}{0.35mm}
\setlength{\mathindent}{8mm}

%\newcounter{mypage}
%\setcounter{mypage}{1}

\pagestyle{fancy}

\lhead{\large\textbf{Pr{\"u}fungskorrektur-Liste}}
\chead{}
\rhead{}
\cfoot{
  \begin{picture}(0,0)
    \thicklines
    \put(-230,20){\textcolor{red}{Datum, Unterschrift Pr{\"u}fer 1}}
    \put(-255,32){\textcolor{red}{\line(1,0){180}}}
    \put(120,20){\textcolor{green}{Datum, Unterschrift Pr{\"u}fer 2}}
    \put(95,32){\textcolor{green}{\line(1,0){180}}}
  \end{picture}
\thepage /\pageref{LastPage}}
%\lfoot{\thesection}%
\lfoot{Berufliches Schulzentrum Leonberg}
%\newcounter{showsectionheaders}
%\setcounter{showsectionheaders}{0}

\definecolor{red}{rgb}{1,0,0} 
\definecolor{green}{rgb}{0.15,0.75,0.15}
\definecolor{blue}{rgb}{0.2,0,1}
\definecolor{yellow}{rgb}{0.7,0.7,0.15}
\definecolor{orange}{rgb}{1,0.65,0.15}
');
    print LATEX "\\rhead{}\n";
    print LATEX "\\rfoot{Created by \\texttt{examplix} on \\today}\n";

    print LATEX "\\chead{}\n";

    print LATEX "\\begin{document}\n";

my $header=0;

# print line for each student
my $count=0;
my $last_class="";
foreach my $student (@stud_res){
    $count++;
    my $student_name="";
    if (exists $student_updates{$student}){
        # mapping exists 
	$student_name=$student_updates{$student};
    } else {
        $student_name=$student;   
    }

    my ($last,$first)=split(/,/,$student_name);
    # remove space in the beginning
    $first =~ s/^ //;

    my $this_class=$students_class{$student};
if ($this_class ne $last_class){

if ($last_class ne ""){
print LATEX ('
\end{longtable}

\newpage

');
}
print LATEX "\\rhead{\\large\\textbf{$this_class}}";
print LATEX ('
\begin{longtable}{|p{3mm}|p{31mm}||p{7mm}|p{5,4mm}|p{5,4mm}|p{5,4mm}|p{5,4mm}|p{5,4mm}|p{5,4mm}|p{5,4mm}|p{5,4mm}|p{5,4mm}|p{5,4mm}||p{7mm}|p{7mm}||p{7mm}|} \hline 
\rule[-2mm]{0mm}{7mm} & 
  &\multicolumn{1}{c|}{\scriptsize\textcolor{red}{\!\!Pr{\"u}f.\,1\!\!}} 
  & & & & & & & & & &
  &\multicolumn{1}{c|}{\scriptsize\textcolor{red}{\!\!Pkte.\,1\!\!}} 
  &\multicolumn{1}{c||}{\scriptsize\textcolor{red}{\!\!Note\,1\!\!}} 
  & \\\\ \nopagebreak \cline{3-15}

\rule[-2mm]{0mm}{7mm} & \textbf{Name}
  &\multicolumn{1}{c|}{\scriptsize\textcolor{green}{\!\!Pr{\"u}f.\,2\!\!}}
  & & & & & & & & & &
  &\multicolumn{1}{c|}{\scriptsize\textcolor{green}{\!\!Pkte.\,2\!\!}}
  &\multicolumn{1}{c||}{\scriptsize\textcolor{green}{\!\!Note\,2\!\!}} 
  &\multicolumn{1}{c|}{\raisebox{1mm}{\!\!$\varnothing$-Note}\!\!} \\\\ \hline \hline 
\endhead 

');

}

$last_class=$this_class;

print LATEX ("\\multicolumn{1}{|r|}{\\rule[-1mm]{0mm}{5mm}\\!\\!\\!\\textbf{$count}\\!\\!}");
    print LATEX ("&\\textbf{$last,}");
    print LATEX ('&\multicolumn{1}{c|}{\textcolor{red}{1}}
  & & & & & & & & & & & & 
  & \\\ \\nopagebreak
');
    # when \cline{3-15} is used there is a pagebreak possible within one student
    # therefore a picture is used to create the line 
    print LATEX ('\rule[-1mm]{0mm}{5mm}\begin{picture}(0,0)\put(118,11){\line(1,0){377}}\end{picture}');
    print LATEX ("& \\textbf{$first}");
    print LATEX ('
  &\multicolumn{1}{c|}{\textcolor{green}{2}} 
  & & & & & & & & & & & &
  & \\\\ \hline\hline\pagebreak[3]
');
}

print LATEX ('
\end{longtable}
');
    print LATEX "\\end{document}\n";
    close(LATEX);
  my $path="${prefix_work}${create_lists}"."/lists";
  system("cd $path; latex correction.tex $dev_null");
  system("cd $path; latex correction.tex $dev_null");
  system("cd $path; dvips correction.dvi $dev_null 2>&1");
  system("cd $path; ps2pdf correction.ps $dev_null");

  system("cd $path; rm correction.aux");
  system("cd $path; rm correction.dvi");
  system("cd $path; rm correction.log");

}


sub dprint {
    print LATEX @_;
    print KAMMER @_;
}



sub latex_preamble {
    my $result_latex=&latexize($result);

    open (KAMMER, ">${prefix_work}$result/results/${mode}/kammer-$result.tex");
    open (KAMMERCSV, ">${prefix_work}$result/results/${mode}/kammer-$result.csv");
    open (LATEX, ">${prefix_work}$result/results/${mode}/results-$result.tex");

    # csv header
    print KAMMERCSV "BSZ-Nr.;Nachame;Vorname;WSK-Note;WSK-Punkte;KKT-Note;KKT-Punkte;BSZ-Klasse\n";

    &dprint(${DevelConf::latex_preamble});
    print LATEX "\\rhead{\\texttt{$result_latex-$mode}}\n";
    &dprint("\\rfoot{Created by \\texttt{examplix} on \\today}\n");

    if (defined $typeout{'title'}){
        print LATEX "\\chead{\\textbf{$typeout{'title'}}}\n";
    } else {
        print LATEX "\\chead{}\n";
    }

    if ($final_version==0){
        print LATEX "% option --final not given\n";
        print LATEX "\\usepackage[german,timestamp,dark]{draftcopy}\n";
        print LATEX "\\draftcopyFirstPage{1}\n";
    } else {
        print LATEX "% option --final given\n";
        print LATEX "%\\usepackage[german,timestamp,dark]{draftcopy}\n";
        print LATEX "%\\draftcopyFirstPage{1}\n";
    }

    &dprint("\\begin{document}\n");

    if ($mode eq "exam"){
        my $result_latex=&latexize($result);
        my $mode_latex=&latexize($mode);
        print LATEX "\\textbf{\\huge Pr\\\"{u}fung $result_latex-$mode_latex:}\n";
        print LATEX "\\tableofcontents\n";
        print LATEX "\\newpage\n";
        &print_correction_lists($result);
        print KAMMER "\\chead{\\textbf{Pr{\\\"u}fungsergebnisse $result_latex-$mode_latex}}\n";
    }
}



sub print_correction_lists {
    my ($option)=@_;
    my %all_corrections=();
    open (EXAM, "${prefix_work}$option/${mode}.cfg") || 
      die "\n   Fehler: ${prefix_work}$option/${mode}.cfg not found! \n\n";
    while (<EXAM>){
        s/^ //g; # Leerzeichen am Zeilenangfang entfernen
        if(/^\#/ or 
           /^\s/ or
           /^SHOW_SUBJECT/ or
           /^EXAMONLY_SUBJECT/ or
           /^LOOP_SUBJECT/ or
           /^EXTRA_SUBJECT/ 
          ){ # # am Anfang bedeutet Kommentarzeile
            next;
        }
        chomp();
        my ($day,
            $problem,
            $subject,
            $factor,
            $corr_1,
            $group_1,
            $corr_2,
            $group_2,
            $corr_3,
            $group_3,
           )=split(/;/);

        # Build the hash
        if($corr_1 ne ""){
         $all_corrections{$day}{$corr_1}{$subject}{"Erstkorrektur"}{$problem}="";
        }
        if($corr_2 ne ""){
         $all_corrections{$day}{$corr_2}{$subject}{"Zweitkorrektur"}{$problem}="";
        }
        if($corr_3 ne ""){
         $all_corrections{$day}{$corr_3}{$subject}{"Drittkorrektur"}{$problem}="";
        }
    }
    print LATEX "\\section{Korrigieren - Wer korrigiert was?}\n";
    foreach my $day (@days){
        my %teachers_table=();
        my @teachers_table=();
        my %subjects_table=();
        my @subjects_table=();
        my $day_long=&translate_to_long($day); 
        print LATEX "\\subsection{$day_long}\n";
        if($log_level>=3){
           print "Day $day:\n";
        }
        while (my ($teacher,$v) = each %{ $all_corrections{$day}  } ){
           if($log_level>=3){
              print "   $teacher  : $v \n";
	   }
           # add teacher to hash of teachers
           if (not exists $teachers_table{$teacher}) {
	       $teachers_table{$teacher}="";
           }
           while (my ($subject,$v) = each %{ $all_corrections{$day}{$teacher}  } ){
               if($log_level>=3){
                  print "      $subject  : $v \n";
	       }
               # add subject to hash of subjects
               if (not exists $subjects_table{$subject}) {
	           $subjects_table{$subject}="";
               }
           }
        }  
        # create ascibetical list of teachers
        while (my ($teacher,$v) = each %teachers_table ){
	    push @teachers_table, $teacher;
        }
        @teachers_table = sort @teachers_table;

        if($log_level>=3){
           print "   ascibetical list of teachers:\n";
           foreach my $teacher (@teachers_table){
              print "      $teacher  \n";
           }
        }     

        # create ascibetical list of subjects
        while (my ($subject,$v) = each %subjects_table ){
	    push @subjects_table, $subject;
        }
        @subjects_table = sort @subjects_table;

        if($log_level>=3){
           print "   ascibetical list of subjects:\n";
           foreach my $subject (@subjects_table){
              print "      $subject  \n";
           }
        }  
 
        # create LATEX code
        my $columns=$#subjects_table+2;

        print LATEX "\\begin{center}\n";
        print LATEX "\\begin{tabular}{|l|";
	foreach my $subject (@subjects_table){
            print LATEX "c|";
	}
	print LATEX "l|} \\hline \n";

        # header
        print LATEX "\\rule[-3mm]{0mm}{9mm} & ";
        my $header = join " & ", @subjects_table;
        print LATEX "$header";
        print LATEX " & \\\\ \\hline\\hline \n";

        # the teachers
        foreach my $teacher (@teachers_table){
            foreach my $num (@numstrings){
	       my $color="";
               if ($num eq "Erstkorrektur"){
		   $color="red";
      	           print LATEX "\\rule{0mm}{4.5mm}\\textbf{$teacher} ";
               } elsif ($num eq "Zweitkorrektur"){
		   $color="green";
               } elsif ($num eq "Drittkorrektur"){
                   $color="blue";
               }
               foreach my $subject (@subjects_table) {
                  my $problems="";
		  my @problem_list=();
                  if($log_level>=3){
       	             print "    Fach ${subject}:\n";
		  }
                  while (my ($problem,$v) = each
                    %{ $all_corrections{$day}{$teacher}{$subject}{$num}  } ){
                     if($log_level>=3){
                        print "      $problem  : $v \n";
		     }
                     push @problem_list, $problem;
                  }
                  @problem_list = sort @problem_list;
		  $problems = join ", ",@problem_list;
                  if ($problems eq ""){
                      $problems="---";
                  }
                  if($log_level>=2){
                     printf "   %-14s %-7s %-20s %-30s \n",
                         $num, $teacher,$subject,$problems;
		  }
                  print LATEX " & \\textcolor{$color}{$problems} \n"; 
	       }

               if ($num eq "Erstkorrektur"){
                   print LATEX " & \\textcolor{red}{$num} \\\\[1mm] \n";
	       } elsif ($num eq "Zweitkorrektur"){
                   print LATEX " & \\textcolor{green}{$num} \\\\[1mm] \n";
 	       } elsif ($num eq "Drittkorrektur"){
                   print LATEX " & \\textcolor{blue}{$num} \\\\[1mm] \n";
               } else {
                   print LATEX " & $num \\\\[1mm] \n";
               }

            }
            print LATEX "  \\hline \\hline \n";
        }
        print LATEX "\\end{tabular}\n";
        print LATEX "\\end{center}\n";
    }
}


sub latex_headers {
   my ($sub,$num_null,$i_sub)=@_;
   if ($#problems > $max_problems){
      $landscape=1;
      print LATEX "\\newpage \n\n";
      print LATEX "\\begin{landscape}\n\n";
   } else {
      $landscape=0;
   }
   if ($i_sub > 1){
       # do not print on first subject
       print LATEX "\\vfill\n\n";
       print LATEX "\\pagebreak\n\n";
   }
   print LATEX "\\subsection{$sub ($latex_title)}\n";
   print LATEX "\\begin{longtable}{|r|l|";
   foreach my $col (@problems){
           print LATEX "c|";
   }
   if ($num_null eq "Erstkorrektur" or $num_null eq "Zweitkorrektur"){
      print LATEX "|c";
   }
   print LATEX "|c||c|}\\caption{$sub--Ergebnisse}\\\\ \\hline \n";


   # Header 1
   print LATEX " & & ";
   foreach my $col (@problems){
       if ($narrow==1){
           print LATEX "\\!\\!$col\\!\\! & ";
       } else {
           print LATEX "\\!$col\\! & ";
       }
   }
   if ($num_null eq "Erstkorrektur" or $num_null eq "Zweitkorrektur"){
      print LATEX " &";
   }
   print LATEX " & \\\\ \\nopagebreak \n";


   # Header 2
   print LATEX " & & ";
   my $i=0;
   foreach my $day (@days){
       # counting the elements af array
       # fetch problem as rhe $i'th element of problem array
       # from Header 1
       my $corr=$all_correctors{$day}{$problems[$i]}{$sub};
       $i++;
       if ($mode eq "exam"){
           print LATEX "\\footnotesize $day & ";
       } else {
           print LATEX "\\footnotesize $day ($corr)& ";
       }
   }
   if ($num_null eq "Erstkorrektur" or $num_null eq "Zweitkorrektur"){
      print LATEX " &";
   }
   print LATEX " & \\\\ \\nopagebreak\n";


   # Header 3
   if ($narrow==1 and $landscape==1){
       print LATEX " & \\!\\!\\textbf{Name}\\!\\! & ";
   } else {
       print LATEX " & \\textbf{Name} & ";
   }
   foreach my $factor (@factors){
      print LATEX "\\!x$factor\\! & ";
   }
   print LATEX " \$\\Sigma\$ ";
   if ($num_null eq "Erstkorrektur" or $num_null eq "Zweitkorrektur"){
      print LATEX "& \$\\varnothing\$ ";
   }
   print LATEX "&  \$\\varnothing_{ges.}\$ \\\\ \\hline \\hline \n";
   print LATEX "\\endhead \n";
}



sub latex_footer {
   # Line with averages

   my ($num_null) = @_;
   if ($num_null eq "Erstkorrektur" or $num_null eq "Zweitkorrektur"){
      # do nothing
   } else {
      print LATEX " \\hline ";

      # Calculate real number of students with this subject
      #my $students_num_real=$students_num-$students_num_without_subject;
      # Footer 1
      print LATEX " \\rule[-2mm]{0mm}{6.3mm}& \$\\varnothing\$& ";

      my $array_index=0;
      foreach my $sum (@sums_class){
          my $ave;
          if ($sums_students_with_result[$array_index]==0){
	      $ave="---";
          } else {
  	      $ave = $sum/$sums_students_with_result[$array_index];
              $ave = &two_decimal($ave);
              $ave = &dot_to_comma($ave);
	  }
         # print LATEX "${ave}_{$sums_students_with_result[$array_index]} & ";
         print LATEX "\$${ave}_{($sums_students_with_result[$array_index])}\$ & ";

	 $array_index++;
      }
      if ($sum_students_with_average==0){
	  $average_class="---";
      } else {
          $average_class = $sum_class/$sum_students_with_average;
          $average_class = &two_decimal($average_class);
          $average_class = &dot_to_comma($average_class);
      }
      print LATEX " & \$${average_class}_{($sum_students_with_average)}\$ \\\\ \\hline\n";
   }





}


sub latex_end {
    if (-e "$result/teachers.cfg"){
	open (TEACHERS, "<${prefix_work}$result/teachers.cfg");
        print LATEX "\\section{Korrigierende Lehrer}\n";
        print LATEX "\n\\bigskip\n\n";
        print LATEX "\n\\begin{center}\n\n";
        print LATEX "\\begin{tabular}{|c|lcl|} \\hline\n";
        print LATEX "\\rule{0mm}{6mm}\\large Kürzel&\\large Name&&\\large Unterschrift\\\\[1mm] \\hline\\hline\n";
        print LATEX "&&&\\\\[4mm]\n";

        while (<TEACHERS>){
            chomp();
	    my ($short,$name)=split(/:/);
            if (exists $teachers_seen{$short}){
                print LATEX "\\large\\textbf{$short} & ",
                            "\\large\\textbf{$name} & : & ",
                            "\\rule[-2mm]{100mm}{0.3mm}\\hspace{5mm} \\\\[8mm]\n";
	    }
        }
        print LATEX "\\hline\n\\end{tabular}\n\n";
        print LATEX "\n\\end{center}\n\n";

    }

    print LATEX "\\end{document}\n";
    print KAMMER "\\end{document}\n";
    close (LATEX);
    close (KAMMER);
    close (KAMMERCSV);
}


sub compile_latex_file {
    my ($abs_file) = @_;
    my $file=basename($abs_file,".tex");
    my $dir=dirname($abs_file);
    my $file_tex=$file.".tex";
    my $file_dvi=$file.".dvi";
    my $file_ps=$file.".ps";
    my $file_log=$file.".log";
    my $file_aux=$file.".aux";
    system("cd $dir; latex $file_tex $dev_null");
    system("cd $dir; latex $file_tex $dev_null");
    system("cd $dir; dvips $file_dvi $dev_null 2>&1");
    system("cd $dir; ps2pdf $file_ps $dev_null");
    system("cd $dir; rm $file_log");
    system("cd $dir; rm $file_aux");
    system("cd $dir; rm $file_dvi");
}



sub compile_latex {
    my ($result,$file,$dir,$kammer) = @_;
    if (not defined $kammer){
        $kammer="";
    }
    my $result_path = "${prefix_work}$result/${dir}/${mode}";

    if ($kammer eq "kammer"){
        print "Compiling generated file: ${result_path}/kammer-${file}.tex\n";
        system("cd $result_path; latex kammer-${file}.tex $dev_null");
        system("cd $result_path; latex kammer-${file}.tex $dev_null");
    } else {
        print "Compiling generated file: ${result_path}/${dir}-${file}.tex\n";
        system("cd $result_path; latex ${dir}-${file}.tex $dev_null");
        system("cd $result_path; latex ${dir}-${file}.tex $dev_null");
        system("cd $result_path; latex ${dir}-${file}.tex $dev_null");
    }

    if ($kammer eq "kammer"){
        print "Creating file: ${result_path}/kammer-${file}.ps\n";
        system("cd $result_path; dvips kammer-${file}.dvi $dev_null 2>&1");
    } else {
        print "Creating file: ${result_path}/${dir}-${file}.ps\n";
        system("cd $result_path; dvips ${dir}-${file}.dvi $dev_null 2>&1");
    }

    if ($kammer eq "kammer"){
        print "Creating file: ${result_path}/kammer-${file}.pdf\n";
        system("cd $result_path; ps2pdf kammer-${file}.ps $dev_null");
    } else {
        print "Creating file: ${result_path}/${dir}-${file}.pdf\n";
        system("cd $result_path; ps2pdf ${dir}-${file}.ps $dev_null");
    }

    if ($kammer eq "kammer"){
        system("cd $result_path; rm kammer-${file}.aux");
        system("cd $result_path; rm kammer-${file}.dvi");
        system("cd $result_path; rm kammer-${file}.log");
        system("cd $result_path; rm kammer-${file}.toc $dev_null 2>&1");
    } else {
        system("cd $result_path; rm ${dir}-${file}.aux");
        system("cd $result_path; rm ${dir}-${file}.dvi");
        system("cd $result_path; rm ${dir}-${file}.log");
        system("cd $result_path; rm ${dir}-${file}.toc $dev_null 2>&1");
    }

    if (-e "/usr/bin/kghostview" and $viewer==1){
       print "Starting viewer.\nHit Ctrl-C to terminate the viewer ...\n";
       system("cd $result_path; kghostview ${dir}-${file}.ps");
       print "All Done.\n";
    } elsif ($viewer==0){
	print "No viewer requested ...\n"; 
        print "All Done.\n";
    } else {
	print "Viewer /usr/bin/kghostview not found. Skipping ...\n"; 
        print "All Done.\n";
    } 
}



sub mark_2_points {
    my ($mark) = @_;
    my $points;
    if (not defined $mark){
	$points="";
        return $points;
    }
    if (not exists $valid_marks{$mark}){
	$points="";
        return $points;
    }
    if (exists $kammer_key{$mark}){
        $points=$kammer_key{$mark};
    } else {
        print "\nCould not resolve $mark to points\n\n";
        exit;
    }
    return $points;
}


sub one_decimal {
    my ($float) = @_;
    my $one_dec;
    if (exists $valid_marks{$float}){
        # nothing to change
        # would be wrong in some cases when
        # worked on by the other functions
	$one_dec = $float;
    } else {
        # cutting off after one 
        $one_dec = floor(10*${float})/10;
    }
    #$one_dec =~ s/\./,/;
    return $one_dec;
}


sub two_decimal {
    my ($float) = @_;
    if (not defined $float){
	return "";
    }
    my $two_dec = int(100*$float)/100;
    #$two_dec =~ s/\./,/;
    return $two_dec;
}



sub final_mark {
    my ($mark) = @_;
    my $final_mark;
    if ($mark eq "1.5"){
       $final_mark="2";
    } elsif ($mark < 1.5){
       $final_mark="1";
    } elsif ($mark eq "2.5"){
       $final_mark="3";
    } elsif ($mark < 2.5){
       $final_mark="2";
    } elsif ($mark eq "3.5"){
       $final_mark="4";
    } elsif ($mark < 3.5){
       $final_mark="3";
    } elsif ($mark eq "4.5"){
       $final_mark="5";
    } elsif ($mark < 4.5){
       $final_mark="4";
    } elsif ($mark eq "5.5"){
       $final_mark="6";
    } elsif ($mark < 5.5){
       $final_mark="5";
    } else {
       $final_mark="6";
    }
#    my $mark = int(10*$mark)/10;
#    my $final_mark = sprintf("%.0f", $mark);
    return $final_mark;
}



sub get_result_fromhash {
    my ($student,$corrector,$subject,$num,$day,$problem) = @_;
    my $subject_short=&translate_to_short($subject);
    if($log_level>=3){
       print "    Student:    $student \n";
       print "    Corrector:  $corrector \n";
       print "    Subject:    $subject \n";
       print "    Sub.-short: $subject_short \n";
       print "    Num:        $num \n";
       print "    Day:        $day \n";
       print "    Problem:    $problem \n";
    }
    ### fix this ???????????????????????????????? make th 1 in total_average_od1
    # dependent on option
    my $teacher_level_average;
    my $mark;
    if ($midyear_opt==1){
        $mark=$all_marks{$student}{$corrector}{$subject}{'Halbjahr'}{$day}{$problem};
#        $teacher_level_average=$metadata_teacher_level{"test-class"}{$subject_short}
#              {'students'}{$student}{'total_average_od1'};
        $teacher_level_average=$metadata_teacher_level{"test-class"}{$subject_short}
              {'students'}{$student}{$corrector}{'total_average_od1'};
    } elsif ($year_opt==1){
        $mark=$all_marks{$student}{$corrector}{$subject}{'Schuljahr'}{$day}{$problem};
        $teacher_level_average=$metadata_teacher_level{"test-class"}{$subject_short}
              {'students'}{$student}{$corrector}{'total_average_od2'};
#        $teacher_level_average=$metadata_teacher_level{"test-class"}{$subject_short}
#              {'students'}{$student}{'total_average_od2'};
    } elsif ($exam==1){
        $mark=$all_marks{$student}{$corrector}{$subject}{$num}{$day}{$problem};
    }
    # take care, that $mark contains decimal with dot
    # -300: ignore
    # -200: not found
    # -100: empty
    $mark=-200 if not defined $mark; 
    $teacher_level_average=-200 if not defined $teacher_level_average; 
    $mark =~ s/,/\./;
    if($log_level>=3){
       print "      --> Mark: $mark ($corrector, $problem, class teacher level)\n";
       print "      --> Mark: $teacher_level_average",
             " ($corrector, $problem, teacher level average)\n";
    }
 
    my $mark_return=$mark;
    my $override=1;
    if ($mark < 0 and $teacher_level_average!=0 and $mark!=-300){
        # return $teacher_level_average
        $mark_return=$teacher_level_average;
        $override=0;
    }
    if($log_level>=3){
       print "      --> Returned: $mark_return ($override)\n";
    }
    return ($day,$problem,$corrector,$mark_return,$override);
}


sub get_result_slow {
    my ($student,$corrector,$subject,$num,$day,$problem) = @_;
    my $file=$corrector."_".$subject."_".$num."_".$day."_all.xls";
    print "      Looking in $file \n";
    my $path = "$result/collect/$file";
    my $row;
    my $column;
    my $mark;

    if (not -e $path){
	print "$path is missing \n";
         return ("---","---","---",0);
    }

    my $oBook = Spreadsheet::ParseExcel::Workbook->Parse("$path");
    my($iR, $iC, $oWkS, $oWkC);



          foreach my $oWkS (@{$oBook->{Worksheet}}) {
#    $oWkS->{Name} = "Korrekturergebnis";
              print "--------- SHEET:", $oWkS->{Name}, "\n";
               
              $iC=0;
#              for(my $iR = 4;
              for(my $iR = 9;
                  defined $oWkS->{MaxRow} && $iR <= $oWkS->{MaxRow} ; $iR++) {
                   $oWkC = $oWkS->{Cells}[$iR][$iC];
                   #print "( $iR , $iC ) =>", $oWkC->Value, "\n" if($oWkC);
                   if ($oWkC->Value eq $student){
                      #print "ROW:   ($iR,$iC) =>",$oWkC->Value,"\n" if($oWkC);
                      $row=$iR;       
                   }
	       }
                   #look for the correct value
                   for(my $iC = $oWkS->{MinCol} ;
                        defined $oWkS->{MaxCol} && $iC <= $oWkS->{MaxCol} ; $iC++) {
                       $oWkC = $oWkS->{Cells}[3][$iC];

                       if ($oWkC){
                          if  ($oWkC->Value eq $problem){
                            #print "COLUMN:(3,$iC) =>",$oWkC->Value,"\n" if($oWkC); 
                            $column=$iC;       
		          }
                       }

                   }
               $oWkC = $oWkS->{Cells}[$row][$column];
               print "RESULT:($row,$column) =>", $oWkC->Value, "\n" if($oWkC);
               $mark=$oWkC->Value;
          }

    # take care, that $mark contains decimal with dot
    $mark =~ s/,/\./;
    return ($day,$problem,$corrector,$mark);
}




sub create_xls_reg_mark_file {
    my ($opt) = @_;
    my $teacher="class-teacher";
    my $file="";
    if ($exam==1){
        if ($opt eq "exam"){
            $file="Anmeldenoten_all.xls";
        }
    } else {
        if ($opt eq "midyear"){
                $file="override_Halbjahr.xls";
        } elsif ($opt eq "year"){
                $file="override_Schuljahr.xls";
        }
        #$file="override_all.xls";
    } 
    my @problems = &get_loop_subjects();
    my $path_to_create=$prefix.$tasks.'/collect'."/${mode}/".$teacher;
    #my $filepath=$prefix.$tasks.'/tasks'."/${mode}/".$teacher.'/'.$file;
    my $filepath=$prefix.$tasks.'/collect'."/${mode}/".$file;

    print "Creating $filepath\n";
    system("mkdir -p $path_to_create");
    if (-e $filepath and $force==0){
        print "\nWARNING:\n";
        print "  $filepath\n";
        print "exists already! Make sure you know what you do!\n";
        print "use option --force to override!\n\n";
        exit;
    }
    my $excel = new Spreadsheet::WriteExcel( "$filepath" );
    $excel->set_custom_color(40, 238,  160,  111  );

    my $sheet  = $excel -> addworksheet("Anmeldenoten");
    $sheet->protect('examplix');
    $sheet->set_column('A:A',  22);
#    $sheet->set_column('B:B',  18);

    my $color="grey";
    $excel->set_custom_color(40, 50,  90,  120  );
    $color="blue";
    my $numstring="";
    my $day="";
    my $subject="Fach";
    #my $row=1;
    my $column=2;
    my $format = $excel->add_format();
    $format->set_align('left');
    $format->set_bg_color('grey');
    $format->set_border(1);

    my $format_red = $excel->add_format();
    $format_red->set_align('center');
    $format_red->set_bg_color($color);
    $format_red->set_border(1);

    # unlocked to add data
    my $format_empty = $excel->add_format(locked => 0);
    $format_empty->set_border(1);
    $format_empty->set_bg_color(40);

    # inserting the students
#    $row=4;
    my $row=9;
    foreach my $student (@students){
       $sheet -> write( $row, 0, $student, $format );
       $row++;
    }

    # start in this row with headers
    $row=5;

    # inserting the header in the first two lines
    $sheet -> write( 0, 0, $tasks, $format_red );
    $sheet -> write( 1, 0, $teacher, $format_red );
    if ($opt eq "midyear"){
        $sheet -> write( 2, 0, "Halbjahr", $format_red );
    } elsif ($opt eq "year"){
         
        $sheet -> write( 2, 0, "Schuljahr", $format_red );
    }
    $column=1;

    foreach my $subject (@problems){
       my $subject_short=&translate_to_short($subject);
       if (exists $examonly_subject{$subject}){
           next; 
       }
       if ($numstring eq "Jahr") {
          $day=$day."(".$teacher.")";
       }
       $sheet -> write( $row+3, $column, $subject_short, $format_red );
       $sheet -> write( $row+2, $column, $day, $format_red );
       $sheet -> write( $row+1, $column, "", $format_red );
       $sheet -> write( $row+0, $column, $numstring, $format_red );
       my $i;
       for ($i = $row; $i <= $#students+$row+1; $i++) { 
          $sheet -> write( $i+3, $column, "", $format_empty );
       }
       $column++;
    }
    $excel -> close();
    # create a copy in collect
    #system("cp $filepath $filepath_collect");
}


sub create_xls_groups_file {
    my $teacher="class-teacher";
    my $file="";
    if ($exam==1){
        # do nothing
        return;
    } else {
        $file="groups.xls";
    }
    my @problems = &get_loop_subjects();
    my $path_to_create=$prefix.$tasks.'/collect'."/${mode}/".$teacher;
    my $filepath=$prefix.$tasks.'/collect'."/${mode}/".$file;

    print "Creating $filepath\n";

    system("mkdir -p $path_to_create");
    if (-e $filepath and $force==0){
        print "\nWARNING:\n";
        print "  $filepath\n";
        print "exists already! Make sure you know what you do!\n";
        print "use option --force to override!\n\n";
        exit;
    }
    my $excel = new Spreadsheet::WriteExcel( "$filepath" );
    $excel->set_custom_color(40, 238,  160,  111  );

    my $sheet  = $excel -> addworksheet("Anmeldenoten");
    $sheet->protect('examplix');
    $sheet->set_column('A:A',  22);

    my $color="grey";
    $excel->set_custom_color(40, 50,  90,  120  );
    $color="blue";
    my $numstring="";
    my $day="";
    my $subject="Fach";
    #my $row=1;
    #my $row=6;
    my $format = $excel->add_format();
    $format->set_align('left');
    $format->set_bg_color('grey');
    $format->set_border(1);

    my $format_red = $excel->add_format();
    $format_red->set_align('center');
    $format_red->set_bg_color($color);
    $format_red->set_border(1);

    # unlocked to add data
    my $format_empty = $excel->add_format(locked => 0);
    $format_empty->set_border(1);
    $format_empty->set_bg_color(40);

    # inserting the students
#    $row=4;
    my $row=9;
    foreach my $student (@students){
       $sheet -> write( $row, 0, $student, $format );
       $row++;
    }

    # start in this row with headers
    $row=5;

    # inserting the header
    $sheet -> write( 0, 0, $tasks, $format_red );
    $sheet -> write( 1, 0, $teacher, $format_red );
    $sheet -> write( $row+2, 0, "Gewichtung", $format_red );
    $sheet -> write( $row+3, 0, "Gruppierung", $format_red );

    # headers for group columns
    my $column=1;
    foreach my $header (@group_headers){
       if ($numstring eq "Jahr") {
          $day=$day."(".$teacher.")";
       }
       $sheet -> write( $row+0, $column, "comment", $format_empty );
       $sheet -> write( $row+1, $column, "comment", $format_empty );
       # weighting
       $sheet -> write( $row+2, $column, "0", $format_empty );
       # header
       $sheet -> write( $row+3, $column, $header, $format_red );

       my $i;
       for ($i = $row; $i <= $#students+$row+1; $i++) { 
          $sheet -> write( $i+3, $column, "", $format_empty );
       }
       $column++;
    }
    $excel -> close();
}


sub md5sum_file_changed {
    # return 1, if file has changed
    # return 0, if file unchanged
    if ($skip_md5sum_check==1){
        return 1; # force file has changed
    }
    my ($abs_file) = @_;
    my $file=basename($abs_file);
    my $dir=dirname($abs_file);
    my $old_md5sum_file = $dir."/.md5.".$file;
    my $new_md5sum=`md5sum $abs_file`;
    ($new_md5sum) = split(/\s/ , $new_md5sum);
    #print "   : $abs_file\n";
    #print "MD5: $old_md5sum_file\n";
    #print "MD5sum: -->$new_md5sum<-- \n\n";
    if (not -e $old_md5sum_file){
        print "Creating $old_md5sum_file\n";
        open(MD5, ">$old_md5sum_file");
        print MD5 $new_md5sum;
        close (MD5);
        return 1;
    } else {
        my $old_md5sum=`cat $old_md5sum_file`;
        #print "OLD: $old_md5sum\n";
        #print "NEW: $new_md5sum\n";
        if ($old_md5sum eq $new_md5sum){
            return 0;
        } else {
            return 1;
        }
    }
}

sub abs_path_xls_file_teacher {
    my ($file) = @_;
    my ($teacher) = split(/_/,$file);
    my $file_tmp="";
    $file_tmp=$file;
    $file_tmp=~s/\.xls$//;
    $file=$file_tmp."_NOTEN.xls";
    my $subject;
    my ($task_path,@rest)=split(/_/,$file);

    # set filepaths
    my $abs_path=$prefix_work.$result.'/collect'."/${mode}/".
                 $task_path."/".$file;
    if (-e $abs_path){
        # OK
    } else {
        print "File $abs_path does not exist\n";
        exit;
    }
    return ($abs_path,$teacher);
}


sub read_xls_file_teacher {
    #my ($abs_path,$prob) = @_;
    my ($abs_path,$teacher) = @_;
    my $subject;
    print "File to open: $abs_path ($teacher)\n";
    my $oBook = Spreadsheet::ParseExcel::Workbook->Parse("$abs_path");
    my($iR, $iC, $oWkS, $oWkC);
    foreach my $oWkS (@{$oBook->{Worksheet}}) {
        if($log_level>=2){
            print "Reading worksheet $oWkS\n";
        }
        for(my $iC = $oWkS->{MinCol}+1 ;
            defined $oWkS->{MaxCol} && $iC <= $oWkS->{MaxCol} ; $iC++) {

            # go through columns
            if($log_level>=2){
                print "COLUMN $iC\n";
            }
            # subject
            my $oWkC_subject = $oWkS->{Cells}[0][$iC];
            $subject=$oWkC_subject->Value;
            if($log_level>=2){
                print "   SUBJECT: $subject \n"; 
            }
            # part
            my $oWkC_part = $oWkS->{Cells}[1][$iC];
            my $part=$oWkC_part->Value;
            if($log_level>=2){
                print "   PART: $part \n"; 
            }
            # type
            my $oWkC_type = $oWkS->{Cells}[2][$iC];
            my $type=$oWkC_type->Value;
            if($log_level>=2){
                print "   TYPE: $type \n"; 
            }
            # typeorder
            my $oWkC_typeorder = $oWkS->{Cells}[3][$iC];
            my $typeorder=$oWkC_typeorder->Value;
            if($log_level>=2){
                print "   TYPEORDER: $typeorder \n";
            }
            # number
            my $oWkC_number = $oWkS->{Cells}[4][$iC];
            my $number=$oWkC_number->Value;
            if($log_level>=2){
                print "   NUMBER: $number \n"; 
            }
            # effort i. e. KA1
            my $effort=$type.$number;

            # date
            my $oWkC_date = $oWkS->{Cells}[5][$iC];
            my $date=$oWkC_date->Value;
            if($log_level>=2){
                print "   DATE: $date \n"; 
            }
            # description_1
            my $oWkC_description_1 = $oWkS->{Cells}[6][$iC];
            my $description_1=$oWkC_description_1->Value;
            if($log_level>=2){
                print "   DESCRIPTION_1: $description_1 \n"; 
            }
            # description_2
            my $oWkC_description_2 = $oWkS->{Cells}[7][$iC];
            my $description_2=$oWkC_description_2->Value;
            if($log_level>=2){
                print "   DESCRIPTION_2: $description_2 \n"; 
            }
            # weight
            my $oWkC_weight = $oWkS->{Cells}[8][$iC];
            my $weight=$oWkC_weight->Value;
            if($log_level>=2){
                print "   WEIGHT: $weight \n"; 
            }
            # class_count (number of student with a mark in this effort)
            my $class_count=0;
            # class_sum (sum of marks for this effort)
            my $class_sum=0;
            # class average (average mark of students that took this effort)
            my $class_average=0; 

            # save list of efforts
            my $list="List".$part;
            if ($effort ne ""){
                push @{$metadata_teacher_level{'test-class'}{$subject}
                      {'metadata'}{$teacher}{'lists'}{$list}} , $effort;
	    }

            if ($effort ne ""){
                $metadata_teacher_level{"test-class"}{$subject}{'metadata'}{$teacher}
                          {'parts'}{$part}{$effort}{"TYPEORDER"}=$typeorder; 
                $metadata_teacher_level{"test-class"}{$subject}{'metadata'}{$teacher}
                          {'parts'}{$part}{$effort}{"DATE"}=$date; 
                $metadata_teacher_level{"test-class"}{$subject}{'metadata'}{$teacher}
                          {'parts'}{$part}{$effort}{"DESCRIPTION_1"}=$description_1; 
                $metadata_teacher_level{"test-class"}{$subject}{'metadata'}{$teacher}
                          {'parts'}{$part}{$effort}{"DESCRIPTION_2"}=$description_2; 
                $metadata_teacher_level{"test-class"}{$subject}{'metadata'}{$teacher}
                          {'parts'}{$part}{$effort}{"WEIGHT"}=$weight; 
                $metadata_teacher_level{"test-class"}{$subject}{'metadata'}{$teacher}
                          {'parts'}{$part}{$effort}{"PART"}=$part; 
            }

            # read students data
            for(my $iR=9 ;defined $oWkS->{MaxRow} && $iR <= $oWkS->{MaxRow} ;$iR++){

                # student
                my $oWkC_student = $oWkS->{Cells}[$iR][0];
                my $student=$oWkC_student->Value;

                # mark
                my $oWkC_mark = $oWkS->{Cells}[$iR][$iC];
                my $mark=$oWkC_mark->Value;
                if($log_level>=2){
                    print "$iR: $student $mark\n";
                }
                # ????????????ß weiter hier
                if ($mark ne ""){
                    # save mark
#                    $metadata_teacher_level{"test-class"}{$subject}{'students'}
#                            {$student}{$part}{$effort}=$mark; 
                    $metadata_teacher_level{"test-class"}{$subject}{'students'}
                            {$student}{$teacher}{$part}{$effort}=$mark; 

                    # weighted mark
                    my $weighted_mark=$mark*$weight;


                    # zu jedem Halbjahr hinzuzählen sum1, sum2, sum3, ...
                    my $sum_key="sum".$part;
                    my $weight_key="weight".$part;

                    # sum of weighted marks
                     if (exists $metadata_teacher_level{'test-class'}
 			  {$subject}{'students'}{$student}{$teacher}{$sum_key} ){

                         # add weighted mark
                         my $old_weighted_mark=$metadata_teacher_level{"test-class"}
                               {$subject}{'students'}{$student}{$teacher}{$sum_key};
                         my $mew_weighted_mark=$old_weighted_mark+$weighted_mark;
                         # save new weighted mark sum
                         $metadata_teacher_level{"test-class"}{$subject}{'students'}
 		                   {$student}{$teacher}{$sum_key}=$mew_weighted_mark;
                         # add weight
                         my $old_weight=$metadata_teacher_level{"test-class"}
                               {$subject}{'students'}{$student}{$teacher}{$weight_key};
                         my $mew_weight=$old_weight+$weight;
                         # save new weight
                         $metadata_teacher_level{"test-class"}{$subject}{'students'}
 		                   {$student}{$teacher}{$weight_key}=$mew_weight;
                     } else {
                         # create weighted mark
                         $metadata_teacher_level{"test-class"}{$subject}{'students'}
 		                   {$student}{$teacher}{$sum_key}=$weighted_mark;
                         # create weight
                         $metadata_teacher_level{"test-class"}{$subject}{'students'}
 		                   {$student}{$teacher}{$weight_key}=$weight;
                     }

                    # sum up marks for class average
                    $class_count++;
                    $class_sum=$class_sum+$mark;
                    
                }
                my $total_weight=0;
                my $total_sum=0;
                my $total_average=0;
                my $total_average_od=0;
                my $total_average_exact=0;
                # better do that for all existing lists,
                #  instead of fixed value of 10 ???
                for (my $i = 1; $i <= $max_part; $i++) {
                    my $sum_tmp="sum".$i;
                    my $sum_total="total_sum".$i;
                    my $weight_tmp="weight".$i;
                    my $weight_total="total_weight".$i;
                    my $average_total_exact="total_average_exact".$i;
                    my $average_total="total_average".$i;
                    my $average_total_od="total_average_od".$i;

                    # create total sums,weights,averages for student
                    if (exists $metadata_teacher_level{"test-class"}{$subject}
			{'students'}{$student}{$teacher}{$sum_tmp}){
                        # total sum
                        $total_sum=$total_sum+
                           $metadata_teacher_level{"test-class"}{$subject}
                                {'students'}{$student}{$teacher}{$sum_tmp};
                        $metadata_teacher_level{"test-class"}{$subject}
                                {'students'}{$student}{$teacher}{$sum_total}=$total_sum;
                        # total weight
                        $total_weight=$total_weight+
                           $metadata_teacher_level{"test-class"}{$subject}
                                {'students'}{$student}{$teacher}{$weight_tmp};
                        $metadata_teacher_level{"test-class"}{$subject}{'students'}
                                {$student}{$teacher}{$weight_total}=$total_weight;
                        # total average exact
                        $total_average_exact=$total_sum/$total_weight;
                        $metadata_teacher_level{"test-class"}{$subject}{'students'}
                           {$student}{$teacher}{$average_total_exact}=$total_average_exact;
                        # total average
                        $total_average= &two_decimal($total_average_exact);
                        $metadata_teacher_level{"test-class"}{$subject}{'students'}
                                {$student}{$teacher}{$average_total}=$total_average;
                        # one decimal
                        $total_average_od= &one_decimal($total_average_exact);
                        $metadata_teacher_level{"test-class"}{$subject}{'students'}
                                {$student}{$teacher}{$average_total_od}=$total_average_od;
		    }
                }
                # save class sum,count and average
                $metadata_teacher_level{"test-class"}{$subject}{'metadata'}{$teacher}
                          {'parts'}{$part}{$effort}{"class_count"}=$class_count;
                $metadata_teacher_level{"test-class"}{$subject}{'metadata'}{$teacher}
                          {'parts'}{$part}{$effort}{"class_sum"}=$class_sum;
                if ($class_count!=0){
                    my $class_average_exact=$class_sum/$class_count;
                    my $class_average=&two_decimal($class_average_exact);
                    $metadata_teacher_level{"test-class"}{$subject}{'metadata'}{$teacher}
                          {'parts'}{$part}{$effort}{"class_average_exact"}
                        = $class_average_exact;
                    $metadata_teacher_level{"test-class"}{$subject}{'metadata'}{$teacher}
                          {'parts'}{$part}{$effort}{"class_average"}
                        = $class_average;
	        }
	    }
        }

        # doppelte ergebnisse: KA1 2x vorhanden darf nicht gehen

        # checking for lists and sorting them
        # better do that for all existing lists instead of fixed value of 10 ???
        for (my $i = 1; $i <= $max_part; $i++) {
            my $list_tmp="List".$i;
            # sort lists
            if (exists $metadata_teacher_level{'test-class'}
                       {$subject}{'metadata'}{$teacher}{'lists'}{$list_tmp} ){
	       #print "$list_tmp EXISTS \n\n";
               @{$metadata_teacher_level{'test-class'}
                {$subject}{'metadata'}{$teacher}{'lists'}{$list_tmp}} = 
               sort @{$metadata_teacher_level{'test-class'}
	             {$subject}{'metadata'}{$teacher}{'lists'}{$list_tmp}};
           }
        }
    }
    return $abs_path;
}



sub create_latex_file_teacher {
    my ($filepath) = @_;
    @students=&get_students($result,$teacher);

    $filepath=~s/\/collect\//\/results\//;
    $filepath=~s/\.xls$/\.tex/;

    my $dirpath=dirname($filepath);
    my $file=basename($filepath);

    print "DIR:     $dirpath\n";
    print "PATH:    $filepath\n";
    print "FILE:    $file\n";
    my ($teacher) = split(/_/,$file);
    print "TEACHER: $teacher\n";

    my ($user,$subject,$other,${subject_short}) = split(/_/,$file);
    my $result_latex=&latexize($result);

    system("mkdir -p $dirpath");
    open (LATEXTL, ">$filepath");
    print LATEXTL ${DevelConf::latex_preamble};

    print LATEXTL "\\chead{\\textbf{${subject}---${subject_short}}}\n";
    print LATEXTL "\\rhead{\\textbf{$user}}\n";
    print LATEXTL "\\lhead{\\textbf{$result_latex}}\n";
    print LATEXTL "\\rfoot{Created by \\texttt{examplix} on \\today}\n";
    print LATEXTL "\\newcommand{\\bottomrotate}[2]{\\rotatebox[origin=rB]{90}{#1\\hspace{-13mm}}\\hspace{1.5mm}\\rotatebox[origin=rB]{90}{#2\\hspace{-13mm}}}\n";
    print LATEXTL "\\begin{document}\n";

    print LATEXTL "Fehler: keine\n";

    my $header_0="\\begin{longtable}{|r|l||";
    my $header_1="\\rule[-4mm]{0mm}{8mm}& &\n";
    my $header_2="& \\multicolumn{1}{r||}{\\scriptsize{Datum}} &\n";
    my $header_3="& \\multicolumn{1}{r||}{Gewichtung} &\n";
    my $header_4="& Halbjahr&\n";
    my $header_5="& Name &\n";

    for (my $i = 1; $i <= $max_part; $i++) {
        my $list_tmp="List".$i;
        if (exists  $metadata_teacher_level{'test-class'}
                    {$subject_short}{'metadata'}{$teacher}{'lists'}{$list_tmp} ){
           my @list_current=@{$metadata_teacher_level{'test-class'}
                {$subject_short}{'metadata'}{$teacher}{'lists'}{$list_tmp}}; 
           foreach my $effort ( @list_current ){
	       print "   * Effort found: $effort \n";
               my $weight=$metadata_teacher_level{'test-class'}
	       {$subject_short}{'metadata'}{$teacher}{'parts'}{$i}{$effort}{'WEIGHT'};
               my $date=$metadata_teacher_level{'test-class'}
	       {$subject_short}{'metadata'}{$teacher}{'parts'}{$i}{$effort}{'DATE'};
               my $part=$metadata_teacher_level{'test-class'}
	       {$subject_short}{'metadata'}{$teacher}{'parts'}{$i}{$effort}{'PART'};

               $header_0=$header_0."c|";
               $header_2=$header_2."   \\hspace{-1.5mm}\\scriptsize{$date}\\hspace{-1.5mm} &\n";
               $header_3=$header_3."   $weight &\n";
               $header_4=$header_4."   $part &\n";
               $header_5=$header_5."   $effort &\n";
           }

           # add column for average
           $header_0=$header_0."c||";

           # calculation spans +1 array (0 -> 1). +1 (add average column)
           my $part_columns=$#list_current+2;
           my $title = &translate_part_title($i);

           $header_1=$header_1."   \\multicolumn{$part_columns}{c||}{$title} &\n";
           $header_2=$header_2."   &\n";
           $header_3=$header_3."   &\n";
           $header_4=$header_4."   &\n";
           $header_5=$header_5."   \$\\varnothing_{$i}\$ &\n";
        }
    }

    # replace final & with \\
    $header_1=~s/&$/\\\\/;
    $header_2=~s/&$/\\\\/;
    $header_3=~s/&$/\\\\/;
    $header_4=~s/&$/\\\\/;
    $header_5=~s/&$/\\\\/;

    # todo: replace letztes || mit | ?????
    $header_0=$header_0."} \\hline \n";
    $header_1=$header_1." \n";
    $header_2=$header_2." \n";
    $header_3=$header_3." \n";
    $header_4=$header_4." \n";
    $header_5=$header_5."\n\\hline\\hline\n";

    print LATEXTL $header_0;
    print LATEXTL $header_1;
    print LATEXTL $header_2;
    print LATEXTL $header_3;
    print LATEXTL $header_4;
    print LATEXTL $header_5;

    my $count=1;
    foreach my $student (@students){
        my $student_name="";
        if (exists $student_updates{$student}){
            # mapping exists 
	    $student_name=$student_updates{$student};
        } else {
            $student_name=$student;   
        }
        my $line="";
        print "   * $student_name \n";
        $line=$line.$count. " & $student_name &";
        for (my $i = 1; $i <= $max_part; $i++) {
            my $list_tmp="List".$i;
            if (exists  $metadata_teacher_level{'test-class'}
                        {$subject_short}{'metadata'}{$teacher}{'lists'}{$list_tmp} ){
                my @list_current=@{$metadata_teacher_level{'test-class'}
                    {$subject_short}{'metadata'}{$teacher}{'lists'}{$list_tmp}}; 
                foreach my $effort ( @list_current ){
                    my $mark;
                    if (exists  $metadata_teacher_level{'test-class'}
                            {$subject_short}{'students'}{$student}{$teacher}{$i}{$effort} ){
                        $mark = $metadata_teacher_level{'test-class'}
                            {$subject_short}{'students'}{$student}{$teacher}{$i}{$effort};
                    } else {
                        $mark="---";
                    }
#                    my $mark_formatted = &dot_to_comma($mark);
                    my $mark_formatted = &format($mark);
                    $line=$line." $mark_formatted &";
		    #print "   $effort  $mark  $mark_formatted\n";
                    printf "%10s   %-5s %-5s \n",  $effort,$mark, $mark_formatted;
                }

                # add average
                my $avg="total_average".$i;
                my $average = $metadata_teacher_level{'test-class'}
                            {$subject_short}{'students'}{$student}{$teacher}{$avg};
#                my $average_formatted = &dot_to_comma($average);
                my $average_formatted = &format($average);
                $line=$line." $average_formatted &";
            }
        }

        # replace final & with \\
        $line=~s/&$/\\\\/;
        print LATEXTL "$line \n";
        $count++;
    }
    print LATEXTL "\\hline \\hline \n";


    # add average list and descriptions
    my $footer_1=" \\multicolumn{1}{|r}{}& \\multicolumn{1}{r||}{\\rule[-13mm]{0mm}{17mm}Durchschnitt} &\n";
    my $footer_2=" \\multicolumn{2}{r}{\\rule[-30mm]{0mm}{30mm}} &\n";
    for (my $i = 1; $i <= $max_part; $i++) {
        my $list_tmp="List".$i;
        if (exists  $metadata_teacher_level{'test-class'}
                    {$subject_short}{'metadata'}{$teacher}{'lists'}{$list_tmp} ){
            my @list_current=@{$metadata_teacher_level{'test-class'}
                {$subject_short}{'metadata'}{$teacher}{'lists'}{$list_tmp}}; 
            foreach my $effort ( @list_current ){
               my $class_average=$metadata_teacher_level{'test-class'}{$subject_short}
                    {'metadata'}{$teacher}{'parts'}{$i}{$effort}{'class_average'};
               my $class_count=$metadata_teacher_level{'test-class'}{$subject_short}
                    {'metadata'}{$teacher}{'parts'}{$i}{$effort}{'class_count'};
               my $description_1=$metadata_teacher_level{'test-class'}{$subject_short}
                    {'metadata'}{$teacher}{'parts'}{$i}{$effort}{'DESCRIPTION_1'};
               my $description_2=$metadata_teacher_level{'test-class'}{$subject_short}
                    {'metadata'}{$teacher}{'parts'}{$i}{$effort}{'DESCRIPTION_2'};

               my $conv = Text::Iconv->new("WINDOWS-1252","utf8");
               my $description_1_utf8 = $conv->convert($description_1);
               my $description_2_utf8 = $conv->convert($description_2);

               my $class_average_formatted="";
	       if (not defined $class_average){
                   print "Cannot find calculated class average in $subject ",
                         "($subject_short) of $teacher in $effort\n";
	       } else {
                   $class_average_formatted = &dot_to_comma($class_average);
               }
               $footer_1=$footer_1."   \\hspace{-1.1mm}\$${class_average_formatted}_{($class_count)}\$\\hspace{-1.5mm} &\n";
               $footer_2=$footer_2."   \\multicolumn{1}{c}{".
                                   "\\bottomrotate{$description_1_utf8}{$description_2_utf8}} &\n";

            }

            # add average of averages
            $footer_1=$footer_1."   --- &\n";
            $footer_2=$footer_2."   \\multicolumn{1}{c}{\\bottomrotate{}{}} &\n";
        }
    }

    # replace final & with \\
    $footer_1=~s/&$/\\\\/;
    $footer_2=~s/&$/\\\\/;
    print LATEXTL "$footer_1 \n";
    chomp($footer_2);
    print LATEXTL "$footer_2 ";
    print LATEXTL "\n";


    print LATEXTL "\\end{longtable}\n";

    print LATEXTL "\\end{document} \n";
    close (LATEXTL);
    #&compile_latex("$result","$user-$subject","results");
    return $filepath;
}



sub translate_part_title {
    my ($part) = @_;
    my $index=$part-1;
    my $title = $year_part_list[$index];
    if (not defined $title){
        $title=$part;
    }
    return $title;
}





sub read_xls_file_teacher2 {
    my ($file,$prob,$type,$count) = @_;
    my $file_tmp="";
    # type: NOTEN,OVERRIDE 
    if ($type eq "NOTEN"){
        
        $file_tmp=$file;
        $file_tmp=~s/\.xls$//;
        $file=$file_tmp."_".$type.".xls";
    } elsif ($type eq "OVERRIDE") {
        # nix
    } else {
        $type="";
    }
    if (not defined $count){
        # create 10 columns
        $count=10;
    }

    my @problems = ();
    my ($teacher,$subject,$numstring,$day)=split(/_/,$file);
    my $task_path=$teacher;
    # decide if teacher exists
    my ($name)=getpwnam($teacher);
    if (not defined $name){
	print "$teacher is not a system user -> USING class-teacher for tasks\n";
        $task_path="class-teacher";;
    }
    # list of problems       
    for (my $i = 1; $i <= $count; $i++) {
        my $string=$type.$i; 
        push @problems, $string;
    }

    my ($teacher2,$subject2,$num2,$day2) = split(/_/,$file);

    # set filepaths
    my $filepath=$prefix_work.$result.'/collect'."/${mode}/".
                 $task_path."/".$file;
    #my $filepath_collect=$prefix_work.$tasks.'/collect'."/${mode}/".
    #                     $task_path."/".$file;
    print "File to open: $file\n";
    my $oBook = Spreadsheet::ParseExcel::Workbook->Parse("$filepath");
    my($iR, $iC, $oWkS, $oWkC);
    $metadata_teacher_level{$subject2}{$teacher}{$type}{"max_columns"}=0;

    foreach my $oWkS (@{$oBook->{Worksheet}}) {
        # Reading user_factor
        my $oWkC_factor = $oWkS->{Cells}[2][0];
        my $factor = $oWkC_factor->Value;
        $metadata_teacher_level{$subject2}{$teacher}{$type}{"user_factor"}=$factor;

        # Reading user_columns
        my $oWkC_columns = $oWkS->{Cells}[3][0];
        my $user_columns = $oWkC_columns->Value;
        $metadata_teacher_level{$subject2}{$teacher}{$type}{"user_columns"}=$user_columns;

        # Reading comments
        my $column=1;
        foreach my $pro (@problems){
            my $oWkC = $oWkS->{Cells}[1][$column];
            my $comment = $oWkC->Value;
            if ($comment ne ""){
                $metadata_teacher_level{$subject2}{$teacher}{$type}{$pro}{"user_comment"}=$comment;
                print "   * Problem $pro has comment: $comment ($subject2 $type $pro)\n";
	    }
            $column++;
        }

        # Reading data for a user
#        for(my $iR = 4;
        for(my $iR = 9;
            defined $oWkS->{MaxRow} && $iR <= $oWkS->{MaxRow};
            $iR++) {
           # lookup student once
           my $oWkC = $oWkS->{Cells}[$iR][0];
           my $student = $oWkC->Value;
           # for student
           my $sum=0;
           my $average=0;
           my $count=0;
           my $user_count=0;
           my $column=1;
           my $old_pro_sum=0;
           my $old_user_sum=0;

           foreach my $pro (@problems){
               #print "Pro: $pro (column $column)\n";
               my $oWkC2 = $oWkS->{Cells}[$iR][$column];
               my $mark = $oWkC2->Value; 

               if ($mark ne ""){
                   # a mark was found
                   $count++;
                   $sum=$sum+$mark;
                   my $old_max_column =
                      $metadata_teacher_level{$subject2}{$teacher}{$type}{"max_columns"};
                   print "       $student has $mark (sum: $sum) in $pro ($column)\n";
                   $user_teacher_level{$student}{$subject2}{$type}{$pro}=$mark;
                   if ($column > $old_max_column){
                       $metadata_teacher_level{$subject2}{$teacher}{$type}{"max_columns"}=$column;
                   }
                   # sum up marks for a problem
                   if (exists $metadata_teacher_level{$subject2}{$teacher}{$type}
                             {$pro}{"problem_sum"}){
                      $old_pro_sum=$metadata_teacher_level{$subject2}{$teacher}{$type}
                             {$pro}{"problem_sum"};
	           }
                   my $new_pro_sum=$old_pro_sum+$mark;
                   $metadata_teacher_level{$subject2}{$teacher}{$type}
                      {$pro}{"problem_sum"}=$new_pro_sum;
                   # sum up users for a Problem
                   if (exists $metadata_teacher_level{$subject2}{$teacher}{$type}
                      {$pro}{"problem_user_sum"}){
                       $old_user_sum=$metadata_teacher_level{$subject2}{$teacher}{$type}
                           {$pro}{"problem_user_sum"};
	           }
                   my $new_user_sum=$old_user_sum+1;
                   $metadata_teacher_level{$subject2}{$teacher}{$type}
                      {$pro}{"problem_user_sum"}=$new_user_sum;
	       }
               $column++;
	   }
           # calculate the average for the user
           if ($count != 0){
               $average=$sum/$count;
               $user_teacher_level{$student}{$subject2}{$type}{"average"}=$average;
               $user_teacher_level{$student}{$subject2}{$type}{"count"}=$count;
               $user_teacher_level{$student}{$subject2}{$type}{"sum"}=$sum;
           }
        }
        foreach my $pro (@problems){
           # calculate the average for a problem
           my $problem_users_sum=$metadata_teacher_level{$subject2}{$teacher}{$type}{$pro}{"problem_user_sum"};
           if (defined $problem_users_sum){
               my $average=$metadata_teacher_level{$subject2}{$teacher}{$type}{$pro}{"problem_sum"}/$problem_users_sum;
               $average=&two_decimal($average);
               $metadata_teacher_level{$subject2}{$teacher}{$type}{$pro}{"problem_average"}=$average;
           } else {
               $metadata_teacher_level{$subject2}{$teacher}{$type}{$pro}{"problem_average"}=0;
           }
        }
    }
    print "   * Columns to display for ${subject2} ($type): ",
          "$metadata_teacher_level{$subject2}{$teacher}{$type}{'max_columns'}\n";
}



sub create_xls_file {
    my ($file,$prob,$type,$count) = @_;
    # type: NOTEN,OVERRIDE,EXAM
    my $file_tmp; 
    if ($type eq "NOTEN"){
        $file_tmp=$file;
        $file_tmp=~s/\.xls$//;
        $file=$file_tmp."_".$type.".xls";
    } elsif ($type eq "OVERRIDE" or $type eq "EXAM") {
        # nix
    } else {
        $type="";
    }
    if (not defined $count){
        # create 10 columns
        $count=10;
    }
    #print "   File:   $file\n";
    #print "   Prob:   $prob\n";
    #print "   Type:   $type\n";
    my @problems = ();
    my ($teacher,$subject,$numstring,$day)=split(/_/,$file);
    my $task_path=$teacher;
    my $path_to_create=$prefix_work.$tasks.'/collect'."/${mode}/".
                       $task_path;
    my $filepath;

    system("mkdir -p $path_to_create");

    if ($type eq "NOTEN"){
        # teacher level

        # list of problems       
        for (my $i = 1; $i <= $count; $i++) {
            my $string=$type.$i; 
            push @problems, $string;
        }

        # create directories
        my $dirpath=$prefix_work.$tasks.'/collect'."/${mode}/".
                    $task_path;
        system("mkdir -p $dirpath");

        # set filepaths
        $filepath=$prefix_work.$tasks.'/collect'."/${mode}/".
                  $task_path."/".$file;
    } elsif ($type eq "OVERRIDE" or $type eq "EXAM") {
        # class teacher level

        # list of problems
        @problems = split(/;/,$prob);

        # set filepaths
        $filepath=$prefix_work.$tasks.'/collect'."/${mode}/".$file;
    }

    if (-e $filepath and $force==0){
        print "\nWARNING:\n";
        print "  $filepath\n";
        print "exists already! Make sure you know what you do!\n";
        print "use option --force to override!\n\n";
        exit;
    }

    my $excel = new Spreadsheet::WriteExcel( "$filepath" );
    $excel->set_custom_color(40, 238, 160, 111);
# ??? String Noten anpassen
    my $sheet  = $excel -> addworksheet("Noten");
    $sheet->protect('examplix');
    $sheet->set_column('A:A',  22);
    $sheet->set_column('B:Z',  18);

   # numstring erscheint in B1,C1,...
    my $color="grey";
    if ($numstring eq "Erstkorrektur"){
       $excel->set_custom_color(40, 236,  155,  155  );
       $color="red";
       $numstring="Erst.";
    } elsif ($numstring eq "Zweitkorrektur") {
       $excel->set_custom_color(40, 135,  200,  135  );
       $color="green";
       $numstring="Zweit.";
    } elsif ($numstring eq "Drittkorrektur") {
       $excel->set_custom_color(40, 50,  90,  120  );
       $color="blue";
       $numstring="Dritt.";
    } elsif ($numstring eq "Jahr") {
       $excel->set_custom_color(40, 255,  204,  153  );
       $color="orange";
       $numstring="Jahr";
       $sheet->set_column('B:B',  18);
    }
 
    my $row=1;
    my $column=2;

    my $format = $excel->add_format();
    $format->set_align('left');
    $format->set_bg_color('grey');
    $format->set_border(1);

    my $format_red = $excel->add_format();
    $format_red->set_align('center');
    $format_red->set_bg_color($color);
    $format_red->set_border(1);

    # unlocked to add data
    my $format_empty = $excel->add_format(locked => 0);
    $format_empty->set_border(1);
    $format_empty->set_bg_color(40);

    my $format_empty_head = $excel->add_format(locked => 0);
    # 41 = orange
    $excel->set_custom_color(41, 255,  204,  153  );
    $format_empty_head->set_border(1);
    $format_empty_head->set_bg_color(41);

    # inserting the students
    #$row=4; old
    $row=9;
    my $row_students=$row-1;
    foreach my $student (@students){
       $sheet -> write( $row, 0, $student, $format );
       $row++;
    }

    # inserting the header
    #$sheet -> write( 0, 0, $teacher, $format_red );
    #$sheet -> write( 1, 0, $tasks, $format_red );
    $column=1;

    if ($numstring eq "Jahr") {
        $day=$day."(".$teacher.")";
    }

    ##################################################
    # Erste Spalte (Erklärungen, Schüler)
    if ($type eq "NOTEN"){
         # NOTEN
	 my $a1=$tasks."-".$teacher;
         $sheet -> write( 0, 0, $a1, $format_red );
         $sheet -> write( 1, 0, "Halbjahr (1,2,3, ...)", $format_red );
         $sheet -> write( 2, 0, "Typ (KA,M,...)", $format_red );
         $sheet -> write( 3, 0, "Typorder (1,2,3, ...)", $format_red );
         $sheet -> write( 4, 0, "Nummer (1,2,3, ...)", $format_red );
         $sheet -> write( 5, 0, "Datum (xx.yy.zz)", $format_red );
         $sheet -> write( 6, 0, "Beschreibung 1", $format_red );
         $sheet -> write( 7, 0, "Beschreibung 2", $format_red );
         $sheet -> write( 8, 0, "Gewichtung (1,2, ...)", $format_red );

         $sheet->set_row(0,16);
         $sheet->set_row(1,16);
         $sheet->set_row(2,16);
         $sheet->set_row(3,16);
         $sheet->set_row(4,16);
         $sheet->set_row(5,16);
         $sheet->set_row(6,16);
         $sheet->set_row(7,16);
         $sheet->set_row(8,16);
    } elsif ($type eq "OVERRIDE" or $type eq "EXAM") {
         my $a1=$tasks."-".$teacher;
         $sheet -> write( 0, 0, $a1, $format_red );
    } else {
         $sheet -> write( 1, 0, "SONST", $format_red );
    }

    ##################################################
    # Weitere Spalten 
    foreach my $pro (@problems){
        if ($type eq "NOTEN"){
            # NOTEN
            my $subs=&translate_to_short($subject);
            $sheet -> write( 0, $column, $subs, $format_red );
            $sheet -> write( 1, $column, "",    $format_empty_head );
            $sheet -> write( 2, $column, "",    $format_empty_head );
            $sheet -> write( 3, $column, "",    $format_empty_head );
            $sheet -> write( 4, $column, "",    $format_empty_head );
            $sheet -> write( 5, $column, "",    $format_empty_head );
            $sheet -> write( 6, $column, "",    $format_empty_head );
            $sheet -> write( 7, $column, "",    $format_empty_head );
            $sheet -> write( 8, $column, "",    $format_empty_head );
            my $i;
            for ($i = 1; $i <= $#students+1; $i++) { 
                $sheet -> write( $i+$row_students, $column, "", $format_empty );
            }
        } elsif ($type eq "OVERRIDE") {
            # OVERRIDE
            my $part_count=0; 
            foreach my $part (@year_part_list){
                $sheet -> write(4,$column+$part_count,"OVERRIDE",$format_red);
                $sheet -> write(5,$column+$part_count,$part,$format_red);
                $sheet -> write(6,$column+$part_count,$subject,$format_red );
                $sheet -> write(7,$column+$part_count,$day,$format_red );
                $sheet -> write(8,$column+$part_count,$pro,$format_red );
                my $i;
                for ($i = 1; $i <= $#students+1; $i++) { 
                    $sheet -> write($i+$row_students, $column+$part_count,
                                    "", $format_empty );
                }
                $part_count++;
            }
        } elsif ($type eq "EXAM") {
            # EXAM
            $sheet -> write(4,$column,"EXAM",$format_red);
            $sheet -> write(5,$column,"---",$format_red);
            $sheet -> write(6,$column,$subject,$format_red );
            $sheet -> write(7,$column,$day,$format_red );
            $sheet -> write(8,$column,$pro,$format_red );
            my $i;
            for ($i = 1; $i <= $#students+1; $i++) { 
                 $sheet -> write($i+$row_students, $column,
                                "", $format_empty );
            }
        } else {
            $sheet -> write( 5, $column, "Sonst", $format_red );
        }
        $column++;
    }

    ##################################################
    $excel -> close();
    # create a copy in collect
    #system("cp $filepath $filepath_collect");
}





sub create_task_hash {
    my ($option,$teacher) = @_;
    my $tmp="";
    my $new_1="";
    my $new_2="";
    my $new_3="";
    my %filename=();
    my $file_cfg=$prefix_work.$option."/".$mode.".cfg";

    open (EXAM, "$file_cfg") || 
       die "\n   Fehler:  $file_cfg not found! \n\n";
    while (<EXAM>){
        s/^ //g; # Leerzeichen am Zeilenangfang entfernen
        if(/^\#/ or 
           /^\s/ or
           /^SHOW_SUBJECT/ or
           /^EXAMONLY_SUBJECT/ or
           /^LOOP_SUBJECT/ or
           /^EXTRA_SUBJECT/
          # EXAMONLY needs lists 
          ){ # # am Anfang bedeutet Kommentarzeile
            next;
        }
        chomp();
        my ($day,
            $problem,
            $subject,
            $factor,
            $corr_1,
            $group_1,
            $corr_2,
            $group_2,
            $corr_3,
            $group_3,
           )=split(/;/);

        if (not exists $teachers_seen{$corr_1}){
            $teachers_seen{$corr_1}="seen";
        }

        if (defined $corr_2){
            if (not exists $teachers_seen{$corr_2}){
                $teachers_seen{$corr_2}="seen";
            }
        } else {
            $corr_2="";
        }

        if (defined $corr_3){
            if (not exists $teachers_seen{$corr_3}){
                $teachers_seen{$corr_3}="seen";
            }
        } else {
            $corr_3="";
        }

        #$corr_2="" if not defined $corr_2;
        #$corr_3="" if not defined$corr_3;
        $group_2="" if not defined $group_2;
        $group_3="" if not defined $group_3;

        my $filename_1="";
        my $filename_2="";
        my $filename_3="";

        if ($group_1 eq "") {
            $group_1="all";
        }
        if ($group_2 eq "") {
            $group_2="all";
        }
        if ($group_3 eq "") {
            $group_3="all";
        }
 
        # Create file names
        my $type_string="";
        if ($year==1 or $midyear==1){
	    $type_string="Jahr";
        } else {
	    $type_string="Erstkorrektur";
	}

        $filename_1="$corr_1"."_"."$subject"."_".
                     $type_string."_"."$day"."_"."$group_1".".xls";

        # push 
        if (not exists $filename{$filename_1} ){
	    $filename{$filename_1}="$problem";
        } else {
            $tmp=$filename{$filename_1};
            $new_1=$tmp.";".$problem;
            $filename{$filename_1}="$new_1";
        }


        if ("$corr_2" ne ""){       
           $filename_2="$corr_2"."_"."$subject"."_".
                       "Zweitkorrektur"."_"."$day"."_"."$group_2".".xls";
           if (not exists $filename{$filename_2} ){
	       $filename{$filename_2}="$problem";
           } else {
               $tmp=$filename{$filename_2};
               $new_2=$tmp.";".$problem;
               $filename{$filename_2}="$new_2";
           }
        }

        if ("$corr_3" ne ""){       
           $filename_3="$corr_3"."_"."$subject"."_".
                       "Drittkorrektur"."_"."$day"."_"."$group_3".".xls";
           if (not exists $filename{$filename_3} ){
	       $filename{$filename_3}="$problem";
           } else {
               $tmp=$filename{$filename_3};
               $new_3=$tmp.";".$problem;
               $filename{$filename_3}="$new_3";
           }
        }
    }
    close EXAM;
    return %filename;
}





sub create_exam {
    my ($dir) = @_;
    my $chown=0;
    print "Creating encrypted exam for teacher $teacher_opt\n";
    my ($name,$pw,$uid,$gid,$quota,$comment,$gecos,$home);
    my $encrypted_dir="";
    my $decrypted_dir="";
    if ($teacher_opt ne ""){
        # use teachers home to create project
        ($name,$pw,$uid,$gid,$quota,$comment,$gecos,$home)=
                  getpwnam($teacher_opt);
        if (defined $home){
            $encrypted_dir=$prefix.".".$dir;
            $decrypted_dir=$prefix.$dir;
            print "Creating a new encrypted project: \n";
            print "    Decrypted: $decrypted_dir\n";
            print "    Encrypted: $encrypted_dir\n";
            if (-e $decrypted_dir or -e $encrypted_dir){
                print "\n",
                      "ERROR: Dirs/Files exist already. Cannot create!\n",
                      "       Please check manually!\n";
                exit;
            }

            system("mkdir -p $decrypted_dir");
            system("mkdir -p $encrypted_dir");
            print "#########################################################\n";
            print "######## Please use Paranoia modus for examplix! ########\n";
            print "#########################################################\n";
            system("encfs $encrypted_dir $decrypted_dir");
            my $command="/usr/sbin/sophomorix-print --class $class".
                                        " --caller $teacher_opt".
                                        " --netexamplix tmp/$dir";
            if (-x "/usr/sbin/sophomorix-print"){
                print "$command\n";
                system("$command");
            } elsif ($atlantisfile ne "") {
                print "Reading file $atlantisfile\n";
                # saves all students the result file .filter
                my $command="/usr/bin/atlantis-csv-filter-schueler ".
                            "$atlantisfile ".
                            "${prefix}${dir}/students.cfg ".
                            "birthplace";
                print "$command\n";
                system("$command");
                my @classes_wanted = split(/,/,$class);
                #sleep 2;
                open (STUDENT,">${prefix}${dir}/students.cfg") || 
                      die "$! (${prefix}${dir}/students.cf)";
                foreach my $class_wanted (@classes_wanted){
                   open (ALL,"${prefix}${dir}/students.cfg.filter") || 
                         die "$! (${prefix}${dir}/students.cfg.filter)";
                    while(<ALL>){
                        chomp();
                        my ($class_atlantis,$last,$first,
                            $birth,$birthplace) = split(/;/);
                        if ($class_atlantis eq $class_wanted){   
                            print STUDENT "$last, ${first}:${birth}:",
                                          "${birthplace}:$class_wanted\n";
                        } else {
                            print "$class_atlantis ($last, $first) is not in $class_wanted\n";
		        }
                    }
                    close ALL;
                    # add dummy users
		    foreach my $dummy (@dummy_users){
                        # twice the same entry as an example to renaming a user
                        print STUDENT "$class_wanted, ${dummy}:01.01.1970:",
                                      "Moon:$class_wanted","==",
                                      "$class_wanted, ${dummy}:01.01.1970:",
                                      "Moon:$class_wanted","\n";
                    }
                }
                close STUDENT;
                # removing filtered file from atlantis 
                system("rm ${prefix}/${dir}/students.cfg.filter");
            } else {
                # create example data 
                print "${prefix}${dir}/students.cfg\n";
                open (STUDENT,">${prefix}/${dir}/students.cfg") || 
                      die "Fehler: $!";
                print STUDENT "Galilei, Galileo:31.11.1990:Rom:test-class:15768:\n";
                print STUDENT "Da Vinci, Leonardo:03.06.1990:Venedig:test-class:15769:\n";
                print STUDENT "Newton, Isaak:02.07.1990:London:test-class:15770:\n";
                print STUDENT "Darwin, Charles:01.08.1990:Oxford:test-class:15771:\n";
                close STUDENT;
            }

            # remember to change owner when working 
            # in another users home
            $chown=1;
        } else {
            print "ERROR: Could not find home of teacher $teacher_opt\n"
        }
    }

    # create some dirs
    system("mkdir -p $decrypted_dir/collect");
    system("mkdir -p $decrypted_dir/results");
    if ($year==1 or $midyear==1){
        open (EXAM, ">>$decrypted_dir/year.cfg")|| die "Fehler: $!";
        print EXAM "#FACH(KURZ);Teilfach;FACH(LANG);FAKTOR;KORR;;;\n";
        close EXAM;
        system("mkdir -p $decrypted_dir/collect/year");
        system("mkdir -p $decrypted_dir/results/year");
    } elsif ($exam==1){
        open (EXAM, ">>$decrypted_dir/exam.cfg")|| die "Fehler: $!";
        print EXAM "#TAG;AUFGABE;FACH;FAKTOR;KORR1;GROUP1;KORR2;GROUP2\n";
        close EXAM;
        system("mkdir -p $decrypted_dir/collect/exam");
        system("mkdir -p $decrypted_dir/results/exam");
    }

    # create some files
    system("touch $decrypted_dir/supervisors.cfg");
    system("touch $decrypted_dir/translate.cfg");
    system("touch $decrypted_dir/typeout.cfg");
    # save the teacher as clas-teacher for later reuse
    system("echo $teacher_opt > $decrypted_dir/class-teacher.cfg");
    if ($chown==1){
        my $command="chmod 755 $decrypted_dir";
        print "$command\n";
	system("$command");
        $command="chown -R ${teacher_opt}.$gid $decrypted_dir";
        print "$command\n";
	system("$command");
    }
}




sub  check_options{
   my ($parse_ergebnis) = @_;
   if (not $parse_ergebnis==1){
      my @list = split(/\//,$0);
      my $scriptname = pop @list;
      print "\nYou have made a mistake, when specifying options.\n"; 
      print "See error message above. \n\n";
      print "... $scriptname is terminating.\n\n";
      exit;
   } else {
      print "All options  were recognized.\n";
   }

}


sub get_students {
    my ($kind,$teacher)=@_;
    my @users=();
    my $user;
    my $line;
    my $file1=$prefix_work.$kind."/students-pre.cfg";  # manually added students
    my $file2=$prefix_work.$kind."/students.cfg";      # automatically
    my $file3=$prefix_work.$kind."/students-post.cfg"; # manually added students

    my @files = ($file1,$file2,$file3);
    foreach my $file (@files){   
       print "Opening $file to fetch students ...";
       if (not -e $file){
           print " nonexisting.\n";
           next;
       } else {
           print " existing.\n";
       }
       open (USERS, "<$file");
       while (<USERS>){
          s/^ //g; # Leerzeichen am Zeilenangfang entfernen
          if(/^\#/ or /^\s/){ # # am Anfang bedeutet Kommentarzeile
              next;
          }
          $line=$_;
          chomp($line);
          # $line_part1: old entry
          # $line_part1: updated entry
          my ($line_part1,$line_part2) = split(/==/,$line);
          my ($user,$birthday,$birthcity,
              $class,$uidnumber) = split(/:/,$line_part1);
          my ($user_update,$birthday_update,$birthcity_update,
              $class_update,$uidnumber_update);
          if (defined $line_part2){
              ($user_update,$birthday_update,$birthcity_update,
               $class_update,$uidnumber_update) = split(/:/,$line_part2);
          }  

          # fill user list
          push @users, $user;

          my $student_data="";
          # fill hashes
          if (defined $user_update){
              # second(update) entry in students.cfg exists
              # fill mapping hash
              $student_updates{$user}="$user_update";

              # prepare data for data hash
              if ($birthday_update eq ""){
	          $birthday_update="---";
              }
              if ($birthcity_update eq ""){
	          $birthcity_update="---";
              }
              if ($class_update eq ""){
	          $class_update="---";
              }
              if (not defined $uidnumber_update){
	          $uidnumber_update="---";
              }
              if ($uidnumber_update eq ""){
	          $uidnumber_update="---";
              }

              # fill data hash
              $student_data="\\hspace{4mm}".$birthday_update." \\hspace{1mm} ".
                            $birthcity_update." \\hspace{1mm} ".
                            $class_update." \\hspace{1mm} ".
                            $uidnumber_update;
          } else {
              # no second(update) entry in students.cfg
              # prepare data for data hash
              if ($birthday eq ""){
	          $birthday="---";
              }
              if ($birthcity eq "" or $show_birthcity==0){
	          $birthcity="---";
              }
              if ($class eq ""){
	          $class="---";
              }
              if (not defined $uidnumber){
	          $uidnumber="---";
              }
              if ($uidnumber eq ""){
	          $uidnumber="---";
              }

              # fill data hash
              $student_data="\\hspace{4mm}".$birthday." \\hspace{1mm} ".
                            $birthcity." \\hspace{1mm} ".
                            $class." \\hspace{1mm} ".
                            $uidnumber;
          }

          # old user name --> new data
          $students{$user}=$student_data;
          $students_class{$user}=$class;
       }
       close USERS;
    }
    return @users;
}



sub translate_to_long {
    my ($short)=@_;
    my $long="";
    if (exists $translate_key_short{$short}){
        $long=$translate_key_short{$short};
    } else {
        $long=$short;
    }
    return $long;
}

sub translate_to_short {
    my ($long)=@_;
    my $short="";
    if (exists $translate_key_long{$long}) {
        $short=$translate_key_long{$long};
    } else {
        $short=$long;
    }
    return $short;
}

sub get_translation {
    # open translate.cfg and read it into hashes
    my $path="";
    if ($result ne ""){
        $path=${prefix_work}.$result;
    } elsif ($tasks ne ""){
        $path=${prefix_work}.$tasks;
    } elsif ($create ne ""){
        $path=${prefix_work}.$create;
    }

    my @filelist = ("${DevelConf::translate_file_devel}",
                    "${DevelConf::translate_file}",
                    "$path/translate.cfg");

    foreach my $file (@filelist){
        print "Trying to open $file ...\n";
        if (not -e "$file"){
            print "  * WARNING: Translation file $file not found\n";
            next;
        } else {
	    print "  * Succes, $file exists\n";
        }   
        open (TRANSLATE, "$file");
        while (<TRANSLATE>){
             s/^ //g; # Leerzeichen am Zeilenangfang entfernen
             if(/^\#/ or /^\s/){ # # am Anfang bedeutet Kommentarzeile
                next;
             }
	     chomp();
             my ($short,
                 $long
                )=split(/::/);
             $translate_key_short{$short}=$long;        
             $translate_key_long{$long}=$short;        
        }
        close(TRANSLATE);
    }
}


sub get_correction_numstrings {
    # decide if 
    # Erstkorrektur
    # Erstkorrektur, Zweitkorrektur
    # Erstkorrektur, Zweitkorrektur, Drittkorrektur
    my $level_1=0;
    my $level_2=0;
    my $level_3=0;
    my $path="";
    if ($result ne ""){
        $path=${prefix_work}.$result;
    } elsif ($tasks ne ""){
        $path=${prefix_work}.$tasks;
    } elsif ($create ne ""){
        $path=${prefix_work}.$create;
    } elsif ($update ne ""){
        $path=${prefix_work}.$update;
    }
    if (not -e "$path/${mode}.cfg"){
        print "WARNING: No file $path/${mode}.cfg found\n";
        return 0;
    }    
    print "Opening $path/${mode}.cfg to fetch correction level ...\n";
    open (CORR, "$path/${mode}.cfg") || 
        die "Fehler: $path/${mode}.cfg not found.\n";
    while (<CORR>){
            s/^ //g; # Leerzeichen am Zeilenangfang entfernen
            if(/^\#/ or 
               /^\s/ or
               /^SHOW_SUBJECT/ or
               /^LOOP_SUBJECT/ or
               /^EXTRA_SUBJECT/
              # EXAMONLY needs this 
              ){ # # am Anfang bedeutet Kommentarzeile
               next;
            }
	    chomp();
            my ($day,
                $problem,
                $subject,
                $factor,
                $corr_1,
                $group_1,
                $corr_2,
                $group_2,
                $corr_3,
                $group_3)=split(/;/);

            if (defined $corr_3){
		if ($corr_3 ne ""){
                    $level_3=1;
                }
            }
            if (defined $corr_2){
		if ($corr_2 ne ""){
                    $level_2=1;
                }
            }
            if (defined $corr_1){
		if ($corr_1 ne ""){
                    $level_1=1;
                }
            }
    }
            if ($level_3==1){
		return("Erstkorrektur","Zweitkorrektur","Drittkorrektur");
            }           
            if ($level_2==1){
		return("Erstkorrektur","Zweitkorrektur");
            }           
            if ($level_1==1){
		return("Erstkorrektur");
            }   
            return 0;        
}


sub get_non_sysusers {
    my @sysusers=@_;
    my @non_sysusers=();
    my %sysusers=();
    my %non_sysusers=();
    foreach my $user (@sysusers){
	$sysusers{$user}="sysuser";
    }
    print "${prefix_work}$update/${mode}.cfg\n";
    open (CONF, "${prefix_work}$update/${mode}.cfg") || die "Fehler: $!";
         while (<CONF>){
            s/^ //g; # Leerzeichen am Zeilenangfang entfernen
            if(/^\#/ or 
               /^\s/ or
               /^SHOW_SUBJECT/ or
               /^EXAMONLY_SUBJECT/ or
               /^LOOP_SUBJECT/ or
               /^EXTRA_SUBJECT/
              ){ # # am Anfang bedeutet Kommentarzeile
               next;
            }
	    chomp();
            my ($day,
                $problem,
                $subject,
                $factor,
                $corr_1,
                $group_1,
                $corr_2,
                $group_2,
                $corr_3,
                $group_3)=split(/;/);
            if (not exists $sysusers{$corr_1} and $corr_1 ne ""){
                $non_sysusers{$corr_1}="non-sysuser";
            }
            if (not exists $sysusers{$corr_2} and $corr_2 ne ""){
                $non_sysusers{$corr_2}="non-sysuser";
            }
            if (not exists $sysusers{$corr_3} and $corr_3 ne ""){
                $non_sysusers{$corr_3}="non-sysuser";
            }
	 }
    close(CONF);
    while (my ($user,$tmp) = each %non_sysusers ){
        push @non_sysusers, $user;
    }
    print "Non system users: @non_sysusers\n";
    #print @non_sysusers;
    return @non_sysusers;

}

sub get_sysusers {
    my ($file) = @_;
    my $file_users=$prefix_work.$file;
    my @sys_users=();
    open (SYSUSERS, "<$file_users") || die "Fehler: $file_users not found\n";
    while (<SYSUSERS>){
	chomp();
        if ($_ ne ""){
            push @sys_users, $_;
        }
    }
    close (SYSUSERS);
    return @sys_users;
}


sub check_name {
    my ($pro,$git_option) = @_;
    if (not defined $git_option){
        $git_option="";
    }
    my $midyear=0;
    my $year=0;
    my $exam=0;
    my $abs_pro_decrypted=$prefix."".$pro;
    my $abs_pro_encrypted=$prefix.".".$pro;

    my $message="Projects must have the syntax KLASSE_ART_JAHR-STRING\n".
                "    KLASSE: String\n".
                "       ART: P-T1\n".
                "            P-T2\n".
                "            Jahr\n";
    print "Checking name $pro:\n";
    # checking underscores
    my $underscore_count=$pro=~tr/_//;
    if ($underscore_count!=2){
        print $message;
        print "Please use underscores ($underscore_count found in $decrypt) ",
              "to separate KLASSE,ART,JAHR-STRING\n";
        exit;
    }
    my ($class,$type,$year_string)=split(/_/,$pro);
    print "    KLASSE:  $class\n"; 
    # checking class: everything accepted
    # checking type 
    print "       ART:  $type "; 
    if (not exists $examplix_types{$type} ){
        print $message;
        print "    $type (ART) ist wrong\n";
        exit;
    } else {
        if ($type eq "Jahr"){
            $year=1;
	    print "$type\n";
            &set_mode("year");
        } elsif ($type eq "P-T1" or 
                 $type eq "P-T2" ){
            $exam=1;
            &set_mode("exam");
        } else {
            print "\n";
            print "\nERROR: Could not determine Type of project\n\n";
        }
    }

    # checking year-string
    my $current_year=`date +%Y`;
    chomp($current_year);
    my $last_year=$current_year-1;
    my $pre_last_year=$current_year-2;
    my $next_year=$current_year+1;
    my %allowed_year_strings=($pre_last_year."-".$last_year,"yes",
                              $last_year."-".$current_year,"yes",
                              $current_year."-".$next_year,"yes",
                              "Sommer-".$pre_last_year,"yes",
                              "Sommer-".$last_year,"yes",
                              "Sommer-".$current_year,"yes",
                              "Sommer-".$next_year,"yes",
                              "Winter-".$pre_last_year,"yes",
                              "Winter-".$last_year,"yes",
                              "Winter-".$current_year,"yes",
                              "Winter-".$next_year,"yes"
                             );
    print "      YEAR:  $year_string\n";
    if (not exists $allowed_year_strings{$year_string} ){
        print $message;
        print "    $year_string (JAHR-STRING) ist wrong\n";
        print "    Erlaubt fuer JAHR-STRING sind:\n";
        my @list=();
        while ( my ($key,$value) = each %allowed_year_strings){
            push @list, $key;
            #print "         $key \n";
        }
        @list = sort @list;
        foreach my $item (@list){
            print "         $item\n";
        }
        exit;
    }
    print "  AUTOMODE: (midyear=$midyear year=$year exam=$exam)\n";
    print "   OPTIONS: (midyear=$midyear_opt year=$year_opt exam=$exam_opt)\n";
    print "Successfully checked name $pro\n";

    # checking for git version control
    my $git_dot_dir=$abs_pro_encrypted."/.git";
    if ($git_option eq "AUTOGIT" and 
        not -d $git_dot_dir ){
        print "############################################################\n";
        print "# $pro is $no_git_revision_control\n";
        print "# no $git_dot_dir\n";
        print "# --->>> Adding project to git\n";
        system("cd $abs_pro_encrypted ; git init");
        system("cd $abs_pro_encrypted ; git add .");
        system("cd $abs_pro_encrypted ; git commit -m \"Initial Version: AUTOGIT\"");
        print "############################################################\n";
    } elsif (not -d $git_dot_dir){
        print "GIT: $pro is NOT under git version control\n";
        # nothing to do
    } else {
        print "GIT: $pro is under git version control\n";
        my $command="cd $abs_pro_encrypted; git pull origin master";
        print "$command\n";
        print "\nPassword for the user in the identity ",
              "file ~/.ssh/config";
        my $return=system($command);
        if ($return==0){
            print "\nGit update was successful\n\n";
        } else {
            print "\nWARNING: Git update was NOT successful\n\n";
        }
    } 
    return ($year,$midyear,$exam);
}


sub fetch_projects {
    # identify projects in dir examplix by their middlename(type)
    my ($type) = @_; 
    my @encrypted=();
    my @decrypted=();
    if (not -d $prefix){
        system("mkdir $prefix");
    }
    opendir EXAMPLIX, $prefix or die "Fehler: $! ($prefix)";
       foreach my $dir (readdir EXAMPLIX){
          if ($dir eq "."){next};
          if ($dir eq ".."){next};
          if (-d $prefix.$dir){
              my ($class,$type,$year_string)=split(/_/,$dir);
              if (not defined $type){
                  # skip dirs that have no type-part
                  next;
              } 
              if($dir=~/^\./){
                  # make sure mountpoint exists
                  my $decrypted_dir = $dir;
                  $decrypted_dir=~ s/^\.//;
                  $decrypted_dir=$prefix.$decrypted_dir;
                  system("mkdir -p $decrypted_dir");
                  next;
              } 
              my $students_file_decrypted=$prefix.$dir."/students.cfg";
              my $class_teacher_file_decrypted=$prefix.$dir."/class-teacher.cfg";
              my $translate_file_decrypted=$prefix.$dir."/translate.cfg";
              if (exists $examplix_types{$type} ){
                  # check only dirs that comply to naming convention
                  if (-e $students_file_decrypted or 
                      -e $class_teacher_file_decrypted or 
                      -e $translate_file_decrypted){
                      my $mtab=`cat /etc/mtab | grep encfs`;
                      if($mtab=~/$prefix$dir/){
                          if (-d $prefix.".".$dir){
                              push @decrypted, $dir;
                          } else {
                              print "\nWARNING: $prefix.".".$dir missing\n\n"
                          }
                      } else {
                          print "\nWARNING: $dir seems decrypted,",
                                "           but not im /etc/mtab\n\n";
                      }
                  } else {
                      push @encrypted, $dir;
                  }
              }
          }
       }
    if ($type eq "DECRYPTED"){
        return @decrypted;
    } elsif ($type eq "ENCRYPTED"){
        return @encrypted;
    } else {
        return;
    }
}

sub fetch_remote {
    my ($project) = @_;
    my $abs_path=$prefix.".".$project;
    my $abs_path_dot_git=$prefix.".".$project."/.git";
    my $return="";
    # is it under git Revision control ?
    if (-d $abs_path_dot_git){
        $return=$git_revision_control;
        # is a remote defined ?
        my $string=`cd $abs_path; git remote -v`;
        chomp($string);
        if ($string eq ""){
            $return=$no_remote_string;
        } else {
            my %remotes=();
            my @lines=split(/\n/,$string);
            foreach my $line (@lines){
                my ($name, $remote, $type) = split(/\s/,$line);
                $remotes{$type}=$remote;
            }
            if ($remotes{'(push)'} eq $remotes{'(fetch)'}){
                $return=$remotes{'(push)'};
            } else {
                $return=$remotes{'(push)'}."/".$remotes{'(fetch)'};
            }
        }
    } else {
        $return=$no_git_revision_control;
    }
    return $return;
}


sub encrypt_decrypted_projects {
    print "Doing fusermount -u for all encrypted projects\n";
    my @decrypted=&fetch_projects("DECRYPTED");
    print "    Executing:\n";
    foreach my $pro (@decrypted){
        # encrypt Project
        my $abs_pro=$prefix."".$pro;
        my $abs_pro_dot=$prefix.".".$pro;
        my $command="fusermount -u $abs_pro";
        print "        $command\n";
        system($command);
        # git action
        my $remote = &fetch_remote($pro);
        if ($remote eq $no_remote_string){
            # clone to  a server
            print "There is no remote defined.\n";

            my $git_clone="";
            print "\nDo you want to clone to a remote git server?\n(y/n):";
            while(){# Endlosschleife für die Eingabe
                $git_clone= <STDIN>; # Lesen von Tastatur
                chomp($git_clone); # Newline abschneiden
                if ($git_clone eq "y"){
                    print "Trying to create a remote repository using:\n";
                    print "    $git_ssh_config_entry from .ssh/config\n";

                    # create wildcard repo
                    my $command = "cd /tmp; ".
                          "git clone ${git_ssh_config_entry}:examplix/$pro";
                    print "$command\n"; 
                    system($command);
         
                    # push the local data to the wildcard repo
                    $command = "cd $abs_pro_dot; ".
                           "git push ${git_ssh_config_entry}:examplix/$pro ".
                           "master";
                    print "$command\n"; 
                    system($command);

                    # add remote, so that push and pull works nicely
                    $command = "cd $abs_pro_dot; ".
                           "git remote add origin ".
                           "${git_ssh_config_entry}:examplix/$pro";
                    print "$command\n"; 
                    system($command);
                    last;
                } else {
                    print "NOT cloning to remote server\n";
                    last;
                }
            }
        } else {
            my $git_push="";
            print "\nDo you want to add changes locally ",
                  "and push it to the remote?\n(y/n):\n";
            while(){# Endlosschleife für die Eingabe
                $git_push= <STDIN>; # Lesen von Tastatur
                chomp($git_push); # Newline abschneiden
                if ($git_push eq "y"){
                    # add,commit and push changes to a server
                    print "Pushing to a server with:",
                          " $git_ssh_config_entry from .ssh/config\n";
                    my $command = "cd $abs_pro_dot; ".
                                  "git add .";
                    print "$command\n"; 
                    system($command);
                    $command = "cd $abs_pro_dot; ".
                               "git commit";
                    print "$command\n"; 
                    system($command);
                    $command = "cd $abs_pro_dot; ".
                               "git push --set-upstream origin master";
                    print "$command\n"; 
                    system($command);
                    last;
		} else {
                    print "NOT commiting locally\n";
                    print "NOT pushing remotely\n";
                    last;
                }
	    }
	}
    }
}


sub check_decryption {
    # exit if given project is not decrypted
    # short form of project needed (later: allow abs path also ?????)
    my ($pro) = @_;
    my $abs_pro_decrypted=$prefix."".$pro;
    my $abs_pro_encrypted=$prefix.".".$pro;

    if (-d $abs_pro_decrypted){
        print "OK: Directory for $pro exists.\n";
    } else {
        print "WARNING: Directory for $pro nonexisting\n";
        print "    * creating $abs_pro_decrypted\n";
        system("mkdir -p $abs_pro_decrypted");
    }

    my $abs_pro_students=$abs_pro_decrypted."/students.cfg";
    if (-e $abs_pro_students){
        print "OK: $abs_pro_students exists\n";
    } else {
        print "$abs_pro_students nonexisting\n";
        print "Trying to mount $pro\n";
        my $command="encfs  $abs_pro_encrypted $abs_pro_decrypted";
        print "$command\n";
        system($command);
    }

    # final check: decryption successful?
    if (-e $abs_pro_decrypted."/students.cfg"){
        print "Decryption successful\n";
    } else {
        print "\nERROR: Decryption did not work, please check!\n\n";
        exit;
    }
}


sub set_mode {
    my ($my_mode) = @_;
    $mode=$my_mode;
    if ($my_mode eq "exam"){
        @numstrings=&get_correction_numstrings();
        $latex_title="Pr{\\\"u}fung";
    } elsif ($my_mode eq "year"){
        @numstrings=("Jahr");
        if ($midyear_opt==1){
            $latex_title=$year_part_list[0];
        } elsif ($year_opt==1){
            $latex_title=$year_part_list[1];
        }
    }
}
