package Ernad::Presorter; use strict; use warnings; use Carp qw(confess); use Data::Dumper; use Encode; use File::Basename; use File::Path; use JSON::XS; use Ernad::Dates; use Krichel::File; ## constructor sub new { my $this=shift; my $class=ref($this) || $this; my $o={}; bless $o, $class; my $params=shift; ## copy parameters into the object foreach my $key (keys %{$params}) { $o->{$key}=$params->{$key}; } my $e; if(not defined($o->{'e'})) { if(defined($main::e)) { $o->{'e'}=$main::e; $o->{'impna'}=$o->{'e'}->{'impna'}; $e=$main::e; } } ## set up json $o->{'json'}=JSON::XS->new->utf8->pretty; return $o; } sub motto { my $o=shift; my $motto=shift // ''; if(not $motto) { $motto=$o->{'motto'} or confess "I need a motto here."; if($motto eq 'train') { return $motto; } if($motto eq 'class') { return $motto; } if($motto eq 'seed') { return $motto; } return $o->{'motto'}; } if($motto eq 'train') { $o->{'motto'}='train'; return $motto; } if($motto eq 'class') { $o->{'motto'}='class'; return $motto; } if($motto eq 'seed') { $o->{'motto'}='seed'; return $motto; } confess "I don't know about the motto '$motto',"; } sub deduct_issuedate_from_file { my $o=shift; my $file=shift // confess "I need a file here."; my $bana=basename($file); if(not $bana=~m|^(\d{4}-\d{2}-\d{2})|) { $o->echo(__LINE__,"I have no issuedate on $file"); return 0; } my $issuedate=$1; return $issuedate; } ## reporter sub echo { my $o=shift; my $line_number=shift; my $text=shift or confess "I need something to echo"; my $verbosity=shift // 0; if(not $verbosity=~m|^\d+|) { confess "I don't like the verbosity $verbosity"; } my $me=ref $o; if(not defined($o->{'verbose'}) or ($verbosity < $o->{'verbose'})) { print "$me $line_number | $text", "\n"; } } sub save_json_with_gz { my $o=shift; my $data=shift // confess "I need data here."; my $file=shift // confess "I need a file here."; if(not ref($data)) { confess "I can't save a scalar."; } my $json=$o->{'json'}->encode($data); $json=decode_utf8($json); &Krichel::File::prepare($file); &File::Slurper::write_text($file,$json); system("/bin/gzip -f $file"); $o->echo(__LINE__,"I write $file.gz"); } sub load_json_with_gz { my $o=shift; my $file=shift // confess "I need a file here."; if(not -f $file) { confess "I don't see your file $file."; } my $fh; if($file=~m|\.gz$|) { open $fh , "/bin/gunzip -c $file |"; } else { open $fh, '<', $file; } binmode($fh,'utf8'); my $json=''; my $line; while($line=<$fh>) { $json=$json.$line; } $json=Encode::encode_utf8($json); my $data; eval { $data=$o->{'json'}->decode($json); }; if(not $data) { confess "I could not decode the json in your file '$file'."; } return $data; } sub get_learnports { my $o=shift; my $e=$o->{'e'} // confess "I don't see the erimp."; my @learnports; my $allport=$e->get_allport_repcode(); if($allport) { push(@learnports,$allport); return @learnports; } if(not $e->{'conf'}) { confess "I don't see the configuration"; } if($e->{'conf'}->{'separate_doklis'}) { return $e->list_repcodes(); } ## in extremis, return the impna my $impna=$main::impna // $e->{'impna'} // confess "I don't see the impna."; push(@learnports,$impna); return @learnports; } ## gets the learnport sub get_learnport { my $o=shift; my $e=$o->{'e'} // confess "I don't see the erimp."; ## learnport set $o->echo(__LINE__,"I am setting the learnport.",10); if(defined ($o->{'learnport'}) and $o->{'learnport'}) { $o->echo(__LINE__,"You have set the learnport '". $o->{'learnport'}."'",10); return $o->{'learnport'}; } my $allport=$e->get_allport_repcode(); if($allport) { $o->echo(__LINE__,"The learnport is the allport '$allport'",10); return $allport; } ## base determination from the e->{'repcode'}; if(defined($o->{'e'}->{'repcode'}) and $o->{'e'}->{'repcode'}) { $o->echo(__LINE__,"I set the learnport to report '". $o->{'e'}->{'repcode'}."'",10); return $o->{'e'}->{'repcode'}; } if(defined($o->{'repcode'}) and $o->{'repcode'}) { $o->echo(__LINE__,"I set the learnport to'". $o->{'repcode'}."'",10); return $o->{'repcode'}; } if(defined($o->{'report'}) and $o->{'report'}) { $o->echo(__LINE__,"I set the learnport to report '". $o->{'report'}."'",10); return $o->{'report'}; } if(defined($main::repcode) and $main::repcode) { $o->echo(__LINE__,"I set the learnport to report '". $main::repcode ."'",10); return $main::repcode; } confess "I can't set the learnport."; } ## sets the repcode in an object sub set_report { my $o=shift; my $report=shift // confess "I need a report to set here."; # $o->{'report'}=$report; $o->{'repcode'}=$report; } sub get_repcode { my $o=shift // ''; my $repcode; if($o->{'repcode'}) { $repcode=$o->{'repcode'}; } ## take the repcode from the erimp elsif($o->{'e'}->{'repcode'}) { $repcode=$o->{'e'}->{'repcode'}; $o->{'repcode'}=$repcode; } elsif($main::repcode) { $repcode=$main::repcode; $o->{'repcode'}=$repcode; } elsif($main::report) { $repcode=$main::report; $o->{'repcode'}=$repcode; } else { confess "I need a repcode here."; } ## $o->{'report'}=$repcode; $o->{'repcode'}=$repcode; return $repcode; } #sub set_fitcla { # my $o=shift; # my $fitcla=shift // confess "I need a fitcla to set here."; # $o->{'fitcla'}=$fitcla; #} ## takes a date and finds if it is within the train_limit_by_days # sub is_issuedate_in_range_old { # my $o=shift; # my $e=$o->{'e'} // confess "I need an erimp here."; # my $to_test=shift; # my $date; # if(not &Ernad::Dates::is($to_test)) { # confess "I can't test $to_test for a date."; # } # $date=$1; # if(not &Ernad::Dates::is($date)) { # confess "You made up a date '$date'. I don't take it."; # } # my $train_limit=$e->{'conf'}->{'train_limit_by_days'} // # confess "I don't see your train_limit_by_days."; # my $today=&Ernad::Dates::today; # my $diff_dates=&Ernad::Dates::diff_dates($date,$today); # if($diff_dates > $train_limit) { # return 0; # } # return 1; # } sub is_issuedate_in_range { my $o=shift; my $date=shift; if(not &Ernad::Dates::is($date)) { confess "You made up a date '$date'. I don't take it."; } my $e=$o->{'e'} // confess "I need an erimp here."; my $train_limit=$e->{'conf'}->{'train_limit_by_days'} // confess "I don't see your train_limit_by_days."; my $today=&Ernad::Dates::today; my $diff_dates=&Ernad::Dates::diff_dates($date,$today); if($diff_dates > $train_limit) { return 0; } return 1; } #sub get_fitclas { # my $o=shift; # my $e=$o->{'e'} // confess "I need an erim here."; # $o->{'fitclas'}->{'term'}=1; # $o->{'term_only'}=1; # if(not $e->{'conf'}->{'no_frin'}) { # $o->{'fitclas'}->{'frin'}=1; # $o->{'term_only'}=0; # } # if(not $e->{'conf'}->{'no_frex'}) { # $o->{'fitclas'}->{'frex'}=1; # $o->{'term_only'}=0; # } # return $o->{'fitclas'}; #} #sub deduct_fitcla_from_file { # my $o=shift; # my $file=shift // "I need a file argument here."; # my $bana=basename($file); # #if(not -f $file) { # # confess "I don't see your file $file."; # #} # if(not defined($o->{'fitclas'})) { # $o->get_fitclas(); # } # foreach my $fitcla (keys %{$o->{'fitclas'}}) { # if($bana=~m|\P{L}$fitcla\P{L}|) { # return $fitcla; # } # } # return ''; #} sub get_source_dir { my $o=shift; my $e=$o->{'e'} // confess "I need an erimp here."; if(not $e->{'conf'}->{'no_allport'}) { $o->{'dir'}->{'source'}=$e->{'dir'}->{'allport_sent'}; } elsif(defined($o->{'repcode'})) { $o->{'dir'}->{'source'}=$e->{'report'}->{$e->{'repcode'}}->{'dir'}->{'source'}; } } ## set a directory in the learn directory sub set_dir { my $o=shift; my $what=shift // ''; if(not $what) { print "I need to know what type of directory to set"; } ## use a base dir, meaning without a repcode my $do_base=shift // ''; my $learnport; if(not $do_base) { $learnport=$o->get_learnport() or confess "I need a learnport here"; } my $learn_dir=$o->{'e'}->{'dir'}->{'learn'} or confess "I need a learn_dir here."; if(not -d $learn_dir) { mkpath($learn_dir); } my $dir=$learn_dir.'/'.$what; my $allport_repcode=$o->{'e'}->{'conf'}->{'allport_repcode'}; if($learnport and not $allport_repcode) { $dir.='/'.$learnport; } if(not -d $dir) { mkpath $dir; } $o->{'dir'}->{$what}=$dir; return $dir; } ## clears file from the a directory that have no exfits ## the exfits are responsible for learning limits but these ## limits need to be propagated sub clear { my $o=shift; my $dest_dir=shift; my $restrict=shift // {}; if(not $dest_dir) { confess "I need a destination directory argument here."; } if(not -d $dest_dir) { confess "I don't see the directory $dest_dir."; } my $exfit_dir=$o->set_dir('exfit'); my $sources=$o->get_sources($dest_dir,$exfit_dir,$restrict); ## sources are shown to update, but they need to be empty to be cleared. my $to_clear; foreach my $in_file (keys %$sources) { my $out_file = $sources->{$in_file}; if(not $out_file) { $o->echo(__LINE__,"I remove $in_file"); unlink $in_file; } } return $sources; } ## assumes that there is only one file per issuedate sub get_sources { my $o=shift; my $source_dir=shift // confess "I need a source directory"; if(not -d $source_dir) { confess "I don't see you source_dir '$source_dir'"; } my $destin_dir=shift // confess "I need a destination directory"; if(not -d $destin_dir) { confess "I don't see you destin_dir '$destin_dir'"; } ## an optional restriction my $r=shift // {}; ## takes account of legary restruction only on destation if(not ref $r eq 'HASH') { print Dumper $r; confess "I need this to be an hash_ref now, you gave me '$r'"; } ## remaining files to check my @rest=@_; my $to_do={}; my $e=$o->{'e'} // $main::e // confess "Where is my erimp?"; #my $source_hash=&Ernad::Common::get_hash_of_dates_in_dir($source_dir,$r->{'source'}); my $source_hash=$e->{'d'}->dates($source_dir,$r->{'source'}); #my $destin_hash=&Ernad::Common::get_hash_of_dates_in_dir($destin_dir,$r->{'destin'}); my $destin_hash=$e->{'d'}->dates($destin_dir,$r->{'destin'}); foreach my $date (sort keys %$source_hash) { if($source_hash->{$date}->[1]) { confess "$date is not unique in $source_dir"; } my $source_fufi=$source_dir.'/'.$source_hash->{$date}->[0]; if(not $destin_hash->{$date}) { $to_do->{$source_fufi}=''; next; } if($destin_hash->{$date}->[1]) { confess "$date is not unique in $destin_dir."; } my $destin_fufi=$destin_dir.'/'.$destin_hash->{$date}->[0]; if(&Ernad::Files::does_file_need_renewal($destin_fufi,$source_fufi,@rest)) { $to_do->{$source_fufi}=$destin_fufi; } } ## it's a very bad magic: ## $o->{'sources'}=$to_do; return $to_do; } 1;