text:
=head1 LICENSE

# Copyright [1999-2015] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
# Copyright [2016-2020] EMBL-European Bioinformatics Institute
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

=head1 CONTACT

  Please email comments or questions to the public Ensembl
  developers list at <http://lists.ensembl.org/mailman/listinfo/dev>.

  Questions may also be sent to the Ensembl help desk at
  <http://www.ensembl.org/Help/Contact>.

=cut

=head1 NAME

Bio::EnsEMBL::Pipeline::RuleManager -

=head1 SYNOPSIS

=head1 DESCRIPTION

The RuleManager object is to provide functionailty for creating Jobs, checking if they can run and checking their status and existence

=head1 APPENDIX

The rest of the documentation details each of the object methods. Internal methods are usually preceded with a _

=cut

package Bio::EnsEMBL::Pipeline::RuleManager;

use vars qw(@ISA);
use strict;
use warnings;
use File::Copy;
use Sys::Hostname;
use Socket;
use Bio::EnsEMBL::Pipeline::Config::General;
use Bio::EnsEMBL::Pipeline::Config::BatchQueue;
use Bio::EnsEMBL::Utils::Exception qw(verbose throw warning info);
use Bio::EnsEMBL::Utils::Argument qw( rearrange );
use Bio::EnsEMBL::Pipeline::Job;

@ISA = qw();

=head2 new

  Arg [1]   : Bio::EnsEMBL::Pipeline::DBSQL::DBAdaptor
  Function  : create a Bio::EnsEMBL::Pipeline::RuleManager object
  Returntype: Bio::EnsEMBL::Pipeline::RuleManager
  Exceptions: throws if not passed in a DBAdaptor
  Example   : my $rulemanager = Bio::EnsEMBL::Pipeline::RuleManager
              new->( -DB => $db);

=cut

sub new{
  my ($class,@args) = @_;

  my $self = bless {},$class;

  &verbose('WARNING');

  my ($db, $input_ids, $rules, $queue_manager,
      $awol_mark, $rename, $max_sleep,
      $min_sleep, $base_sleep, $verbose,
      $runner, $output_dir, $job_limit,$delete_lock,$number_output_dirs) = rearrange (
         ['DB',
          'INPUT_IDS',
          'RULES',
          'QUEUE_MANAGER',
          'MARK_AWOL',
          'RENAME_ON_RETRY',
          'MAX_JOB_SLEEP',
          'MIN_JOB_SLEEP',
          'SLEEP_PER_JOB',
          'VERBOSE',
          'RUNNER',
          'OUTPUT_DIR',
          'JOB_LIMIT',
          'UNLOCK',
          'NUMBER_OUTPUT_DIRS',
         ],@args);

  if(!$db){
    throw("Can't run the RuleManager without a dbadaptor");
  }

  $self->db($db);
  $self->delete_lock if $delete_lock ;
  $self->is_locked;
  $self->create_lock;
  $self->number_output_dirs($number_output_dirs) ;
  if(!$queue_manager){
    $queue_manager = $QUEUE_MANAGER; #found in BatchQueue.pm
  }

  my $batch_q_module = "Bio::EnsEMBL::Pipeline::BatchSubmission::$queue_manager";

  my $file = "$batch_q_module.pm";
  $file =~ s{::}{/}g;

  eval {
    require "$file";
  };

  if ($@) {
    throw("Can't find $file [$@]");
  }

  if (!defined($awol_mark)) {
    $awol_mark = $MARK_AWOL_JOBS; #found in BatchQueue.pm;
  }

  if (!defined($rename)) {
    $rename = $RENAME_ON_RETRY; #found in General.pm;
  }

  if (!defined($max_sleep)) {
    $max_sleep = $MAX_JOB_SLEEP; #found in BatchQueue.pm
  }

  if (!defined($min_sleep)) {
    $min_sleep = $MIN_JOB_SLEEP;
  }

  if (!defined($base_sleep)) {
    $base_sleep = $SLEEP_PER_JOB;
  }
  if (!defined($job_limit)) {
    $job_limit = $JOB_LIMIT;
  }

  if (!$runner) {
    $runner = $DEFAULT_RUNNER;
  }

  $self->batch_q_module($batch_q_module);
  $self->input_ids($input_ids) if($input_ids);
  $self->rules($rules) if($rules);
  $self->mark_awol_jobs($awol_mark);
  $self->rename_on_retry($rename);
  $self->max_job_sleep($max_sleep);
  $self->min_job_sleep($min_sleep);
  $self->sleep_per_job($base_sleep);
  $self->be_verbose($verbose);
  $self->runner($runner);
  $self->output_dir($output_dir);
  $self->job_limit($job_limit);
  return $self;
}

###################
#container methods#
###################

=head2 db

  Arg [1]   : Bio::EnsEMBL::Pipeline::DBSQL::DBAdaptor
  Function  : stores the DBadaptor for the object
  Returntype: Bio::EnsEMBL::Pipeline::DBSQL::DBAdaptor
  Exceptions: throws if argument passed in isn't a
              Bio::EnsEMBL::Pipeline::DBSQL::DBAdaptor'
  Example   : my $rules_adaptor = $self->db->get_RulesAdaptor;

=cut

sub db{
  my ($self, $db) = @_;

  if ($db) {
    if (!$db->isa('Bio::EnsEMBL::Pipeline::DBSQL::DBAdaptor')) {
      throw("Can't run the RuleManager with $db you need a ".
            "Bio::EnsEMBL::Pipeline::DBSQL::DBAdaptor");
    }
    $self->{'dbadaptor'} = $db;
  }

  return $self->{'dbadaptor'};
}

=head2 job_adaptor

  Arg [1]   : Bio::EnsEMBL::Pipeline::DBSQL::Adaptormodule
  Function  : store and/or create appropriate adaptors
  Returntype: the requested adaptor
  Exceptions: none
  Example   : my @rules = $self->rule_adaptor->fetch_all;

=cut

sub job_adaptor{
  my ($self, $adaptor) = @_;

  if ($adaptor) {
    $self->{'job_adaptor'} = $adaptor;
  }

  if (!$self->{'job_adaptor'}) {
    my $job_adaptor = $self->db->get_JobAdaptor;
    $self->{'job_adaptor'} = $job_adaptor;
  }
  return $self->{'job_adaptor'};
}

sub analysis_adaptor{
  my ($self, $adaptor) = @_;

  $self->{'analysis_adaptor'} = $adaptor;

  if (!$self->{'analysis_adaptor'}) {
    $self->{'analysis_adaptor'} = $self->db->get_AnalysisAdaptor;
  }
  return $self->{'analysis_adaptor'};
}

sub rule_adaptor{
  my ($self, $adaptor) = @_;

  if ($adaptor) {
    $self->{'rule_adaptor'} = $adaptor;
  }
  if (!$self->{'rule_adaptor'}) {
    my $rule_adaptor = $self->db->get_RuleAdaptor;
    $self->{'rule_adaptor'} = $rule_adaptor;
  }
  return $self->{'rule_adaptor'};
}

sub stateinfocontainer{
  my ($self, $adaptor) = @_;

  if ($adaptor) {
    $self->{'stateinfocontainer'} = $adaptor;
  }
  if (!$self->{'stateinfocontainer'}) {
    my $stateinfocontainer = $self->db->get_StateInfoContainer;
    $self->{'stateinfocontainer'} = $stateinfocontainer;
  }
  return $self->{'stateinfocontainer'};
}

=head2 input_ids

  Arg [1]   : Hash references to hash of input_ids
  Function  : container for hash of input ids keyed on input_id_type
  Returntype: Hash ref
  Exceptions: throws if not passed a hash ref
  Example   : my %input_ids = %{$self->input_ids};

=cut

sub input_ids{
  my ($self, $input_ids) = @_;

  if ($input_ids) {
    throw("Must have a hash ref of input_ids not a $input_ids ")
      unless(ref($input_ids) eq 'HASH');
    $self->{'input_ids'} = $input_ids;
  }

  if (!$self->{'input_ids'}) {
    $self->{'input_ids'} = $self->stateinfocontainer->get_all_input_id_analysis_sets;
  }
  return $self->{'input_ids'};
}

sub empty_input_ids{
  my ($self) = @_;
  $self->{'input_ids'} = undef;
}

=head2 rules

  Arg [1]   : array ref to array of Bio::EnsEMBL::Pipeline::Rule
  Function  : container for array of rules
  Returntype: arrayref
  Exceptions: throws if not passed an array ref;
  Example   : my @rules = @{$self->rules};

=cut

sub rules{
  my ($self, $rules) = @_;
  if ($rules) {
    throw("Must has an array ref of rules not a $rules ")
      unless(ref($rules) eq 'ARRAY');
    $self->{'rules'} = $rules;
  }
  if (!$self->{'rules'}) {
    my @rules = $self->rule_adaptor->fetch_all;
    $self->{'rules'} = \@rules;
  }
  return $self->{'rules'};
}

sub empty_rules{
  my ($self) = @_;
  $self->{'rules'} = undef;
}

=head2 rename_on_retry

  Arg [1]   : int
  Function  : boolean toggle as to whether perform a certain action
  Returntype: int
  Exceptions: none
  Example   : if($self->rename_on_retry)

=cut

#whether to rename job's output files when retried
sub rename_on_retry{
  my $self = shift;

  $self->{'rename_on_retry'} = shift if (@_);
  return $self->{'rename_on_retry'};
}

=head2 mark_awol_jobs

  Arg [1]   : int
  Function  : boolean toggle as to whether perform a certain action
  Returntype: int
  Exceptions: none
  Example   : if($self->mark_awol_jobs)

=cut
#whether to mark jobs which have disappeared from the submission system
sub mark_awol_jobs{
  my $self = shift;

  $self->{'mark_awol_jobs'} = shift if (@_);
  return $self->{'mark_awol_jobs'};
}

=head2 batch_q_module

  Arg [1]   : string, perl path to batch_q_module
  Function  : container for name of batch_q_module
  Returntype: string
  Exceptions: none
  Example   : $self->batch_q_module->job_stats;

=cut

sub batch_q_module{
  my $self = shift;

  $self->{'batch_q_module'} = shift if (@_);
  return $self->{'batch_q_module'};
}

=head2 max_job_sleep

  Arg [1]   : int
  Function  : containers for variables concerned with how long
  the RuleManager sleeps for, or the maximum number of jobs in job_limit's
  case'
  Returntype: int
  Exceptions: none
  Example   :

=cut

sub max_job_sleep{
  my $self = shift;
  $self->{'max_job_sleep'} = shift if (@_);
  return $self->{'max_job_sleep'};
}

=head2 min_job_sleep

  Arg [1]   : int
  Function  : containers for variables concerned with how long
  the RuleManager sleeps for, or the maximum number of jobs in job_limit's
  case'
  Returntype: int
  Exceptions: none
  Example   :

=cut
sub min_job_sleep{
  my $self = shift;

  $self->{'min_job_sleep'} = shift if (@_);
  return $self->{'min_job_sleep'};
}

=head2 sleep_per_job

  Arg [1]   : int
  Function  : containers for variables concerned with how long
  the RuleManager sleeps for, or the maximum number of jobs in job_limit's
  case'
  Returntype: int
  Exceptions: none
  Example   :

=cut
sub sleep_per_job{
  my $self = shift;

  $self->{'sleep_per_job'} = shift if (@_);
  return $self->{'sleep_per_job'};
}

=head2 job_limit

  Arg [1]   : int
  Function  : containers for variables concerned with how long
  the RuleManager sleeps for, or the maximum number of jobs in job_limit's
  case'
  Returntype: int
  Exceptions: none
  Example   :

=cut
sub job_limit{
  my $self = shift;

  $self->{'job_limit'} = shift if (@_);
  return $self->{'job_limit'};
}

=head2 runner/output_dir

  Arg [1]   : string, path to file
  Function  : container for path to output_dir/runner script
  Returntype: string
  Exceptions: none
  Example   :
  Notes     : Do not set output_dir if you want the value to be take
  from the BatchQueue.pm configuration
=cut

sub runner{
  my $self = shift;

  $self->{'runner'} = shift if (@_);
  return $self->{'runner'};
}

sub output_dir{
  my $self = shift;

  $self->{'output_dir'} = shift if (@_);
  return $self->{'output_dir'};
}

=head2 be_verbose

  Arg [1]   : int
  Function  : flag for prints
  Returntype: int
  Exceptions: none
  Example   :

=cut

#called be_verbose so not to interfere with
#Bio::EnsEMBL::Utils::Exception::verbose
sub be_verbose{
  my $self = shift;

  $self->{'verbose'} = shift if (@_);
  return $self->{'verbose'};
}

#################
#Utility methods#
#################

=head2 read_id_file

  Arg [1]   : filename
  Function  : reads a file in the format input_id input_id_type and
  places entires in an 2D hash ref intially keyed on input_id_type
  then on input_id
  Returntype: hash ref
  Exceptions: throws if can't open file'
  Example   : my %ids_not_to_run = $rulemanager->read_id_file($skip_ids);

=cut

sub read_id_file{
  my ($self, $file) = @_;

  my %ids;
  open IDS, "< $file" or throw("Can't open $file");
  while (<IDS>) {
    chomp;
    my ($id, $type) = split;
    if (!$type) {
      throw(" id ".$id ." type ".$type."\n need to know what type the ".
            "input ids in the file are  format should be input_id type\n");
    }
    $ids{$type}{$id} = 1;
  }
  return \%ids
}

=head2 process_types

  Arg [1]   : arrayref to array of strings
  Function  : processes a list of types into a hash
  Returntype: hashref
  Exceptions: throws if not passed an array ref
  Example   : %types_to_run = %{$rulemanager->process_types(\@types)};

=cut

sub process_types{
  my ($self, $types) = @_;

  throw("Can't process $types if not array ref") unless(ref($types) eq 'ARRAY');

  my %types;
  foreach my $type (@$types){
    $types{$type} = 1;
  }
  return \%types;
}

=head2 starts_from_input_ids

  Arg [1]   : arrayref to array of Bio::EnsEMBL::Pipeline::Analysis objects
  Function  : uses these analysis objects to generate hash of input_ids
  Returntype: 2d hashref
  Exceptions: throws if not passed a array ref
  Example   : my $input_id_hash =
  $rulemanager->starts_from_input_ids(\@analyses);

=cut

sub starts_from_input_ids{
  my ($self, $analyses) = @_;

  throw("Can't process $analyses if not array ref") unless(ref($analyses) eq 'ARRAY');

  my %ids;
  foreach my $analysis (@$analyses) {
    my @ids = @{$self->stateinfocontainer->list_input_ids_by_analysis($analysis->dbID)};
    print "analysis ".$analysis->logic_name." has got ".@ids." ids\n";
    foreach my $id (@ids){
      $ids{$analysis->input_id_type}{$id} = 1;
    }
  }
  return \%ids;
}

=head2 create_and_store_job

  Arg [1]   : string, input_id
  Arg [2]   : Bio::EnsEMBL::Pipeline::Analysis
  Arg [3]   : string, directory path  (optional)
  Arg [4]   : string, runner script path (optional)
  Arg [5]   : int, for a boolean flag to mark verbosity (optional)
  Function  : Create a job based on the input_id and analysis passed in.
  Store it in the database and submit to be run
  Returntype: Bio::EnsEMBL::Pipeline::Job
  Exceptions: throws if not passed an input_id or an analysis object and
  if fails to store the job
  Example   : my $job = $rulemanager->create_and_store_job('filename',
                                                           $analysis
                                                           'path/to/dir',
                                                           'runnerscript',
                                                           1);

=cut

sub create_and_store_job{
  my ($self, $input_id, $analysis) = @_;

  if(!$input_id || !$analysis){
    throw("Can't create job without an input_id $input_id or analysis ".
          "$analysis");
  }

  my $job = Bio::EnsEMBL::Pipeline::Job->new
    (
     -input_id => $input_id,
     -analysis => $analysis,
     -output_dir => $self->output_dir,
     -runner => $self->runner,
     -number_output_dirs => $self->number_output_dirs,
    );

  eval{
    $self->job_adaptor->store($job);
  };

  if ($@) {
    throw("Failed to store job ".$job->input_id." ".
          $job->analysis->logic_name." ".$@);
  } else {
    print "Stored ".$job->dbID." ".$job->input_id." ".
      $job->analysis->logic_name."\n" if ($self->be_verbose);
  }
  return $job;
}

=head2 can_job_run

  Arg [1]   : string, input_id
  Arg [2]   : Bio::EnsEMBL::Pipeline::Analysis
  Arg [3]   : string, directory path  (optional)
  Arg [4]   : string, runner script path (optional)
  Arg [5]   : int, for a boolean flag to mark verbosity (optional)
  Function  : Check if a job can be created for an input_id and analysis
              If a job already exists check if it needs to be retried
  Returntype: int
  Exceptions: throws if not passed an input_id or an analysis object and
              if fails to submit the job
  Example   : $rulemanager->can_job_run('filename', $analysis
                                        'path/to/dir',
                                        'path/to/runner', 1);

=cut

sub can_job_run{
  my ($self, $input_id, $analysis, $current_jobs) = @_;

  if (!$input_id || !$analysis) {
    throw("Can't create job without an input_id $input_id or analysis ".
          "$analysis");
  }

  my $job;

  if ($current_jobs->{$analysis->dbID}) {
    my $cj = $current_jobs->{$analysis->dbID};
    #my $status = $cj->current_status->status;

    # This is a hack to get the status at the same time as the job was retrieved
    # _status should be private but current_status is not useful to us here as
    # it will do a new query. Here we don't need the absolutely up-to-the-second
    # status, we can always get the status on the next round of checks. This
    # will also significantly reduce the number of queries of the job table.
    #
    # One problem is jobs which are in the middle of updating their current status.
    # These can be in a state with no current status, which will mean they don't get
    # listed in the current_jobs hash.
    my $status = $cj->{_status}->status;

    if (($status eq 'FAILED' || $status eq 'AWOL') && $cj->can_retry) {
      print "\nRetrying job with status $status!!!!\n" if $self->be_verbose;

      $cj->set_status('CREATED');
      $job = $cj;
    }
  } else {
    $job = $self->create_and_store_job($input_id, $analysis);
  }

  if ($job) {
    eval {
      print "\tBatch running job\n" if $self->be_verbose;
      $job->batch_runRemote;
    };
    if ($@) {
      throw("ERROR running job " . $job->dbID . " ".
            $job->analysis->logic_name." " . $job->stderr_file . " [$@]");
    }
    return 1;
  }

  return 0;
}

=head2 rename_files

  Arg [1]   : Bio::EnsEMBL::Pipeline::Job
  Function  : rename the stderr and stdout files of a job when it is
  retried
  Returntype: int
  Exceptions: throws if not passed a Job object or if rename fails
  Example   : $self->rename_files($cj);

=cut

sub rename_files{
  my ($self, $job) = @_;

  warn('Use of this function is DEPRECATED as it can induce problems');
  if (!$job || !$job->isa("Bio::EnsEMBL::Pipeline::Job")) {
    throw("Need a job object " . $job . " to rename its files\n");
  }
  eval{
    move($job->stdout_file, $job->stdout_file.'.retry'.$job->retry_count);
    move($job->stderr_file, $job->stderr_file.'.retry'.$job->retry_count);
  };

  if ($@) {
    throw("Couldn't rename job ".$job->id."'s output files $@ ");
  }
  return 1;
}

=head2 job_stats/job_limit_check

  Arg [1]   : int, max number of jobs (optional)
  Arg [2]   : array_ref to array of Bio::EnsEMBL::Pipeline::Job objects
  (optional)
  Function  : gets statistics from BatchSubmission module about what
  jobs are running and what their status is then take action on this
  information. job_limit_check checks how many jobs of a defined status
  there are and sleeps if appropriate, job_stats will mark awol jobs
  as well
  Returntype: int
  Exceptions: throws if batch_submission module can't do the method
  job stats'
  Example   : $rulemanager->job_stats;('1000', \@jobs);

=cut

sub job_stats{
  my ($self, $job_limit, $jobs) = @_;

  if (!$job_limit) {
    $job_limit = $self->job_limit;
  }

  # Do job_stats call before getting jobs
  if (!$self->batch_q_module->can('job_stats')) {
    throw($self->batch_q_module." doesn't have the job_stats method");
  }
  my %statuses_to_count = map{$_, 1} @{$JOB_STATUSES_TO_COUNT}; #found in
                                                                #BatchQueue.pm
  my %job_stats = %{$self->batch_q_module->job_stats};

  my @jobs;
  if (!$jobs) {
    @jobs = $self->job_adaptor->fetch_all;
  } else {
    @jobs = @$jobs;
  }

  my @awol_jobs;
  my $job_count = 0;
  JOB:foreach my $job (@jobs) {
    if (!$job_stats{$job->submission_id}) {
      push(@awol_jobs, $job);
      next JOB;
    }
    if ($statuses_to_count{$job_stats{$job->submission_id}}) {
      $job_count++;
    }
  }
  if ($self->mark_awol_jobs) {
    foreach my $awol (@awol_jobs){
      if ($self->valid_statuses_for_awol->{$awol->current_status->status}) {
        $awol->set_status('AWOL');
      }
    }
  }
  if ($job_count >= $job_limit) {
    $self->sleep($job_count, $job_limit);
  }
  return 1;
}

sub job_limit_check{
  my ($self, $job_limit, $jobs) = @_;

  if (!$job_limit) {
    $job_limit = $self->job_limit;
  }

  my @jobs;
  if (!$jobs) {
    @jobs = $self->job_adaptor->fetch_all;
  } else {
    @jobs = @$jobs;
  }

  if (!$self->batch_q_module->can('job_stats')) {
    throw($self->batch_q_module." doesn't have the job_stats method");
  }

  my %statuses_to_count = map{$_, 1} @{$JOB_STATUSES_TO_COUNT}; #found in BatchQueue.pm, PEND for Lsf, qw for gridengine
  my %job_stats = %{$self->batch_q_module->job_stats};
  my $job_count = 0;

  JOB:foreach my $job (@jobs) {
    if ($statuses_to_count{$job_stats{$job->submission_id}}) {
      $job_count++;
    }
  }

  if ($job_count >= $job_limit) {
    $self->sleep($job_count, $job_limit);
  }
  return 1;
}

=head2 valid_statuses_for_awol/kill

  Arg [1]   : none
  Function  : produces a hash of valid statuses to check when either
  marking jobs as awol or killing jobs for running for too long
  Returntype: hashref
  Exceptions: none
  Example   : if($self->
                 valid_statuses_for_awol->{$job->current_status->status})

=cut

sub valid_statuses_for_awol {
  my ($self)  = @_;
  if(!$self->{'status_for_awol'}) {
    my %statuses = map{$_, 1} ('SUBMITTED', 'RUNNING', 'READING',
                               'WRITING', 'WAITING');
      $self->{'status_for_awol'} = \%statuses;
  }
  return $self->{'status_for_awol'};
}

sub valid_statuses_for_kill{
  my ($self)  = @_;

  if (!$self->{'status_for_kill'}) {
    my %statuses = map{$_, 1} ('RUNNING', 'WAITING');
      $self->{'status_for_kill'} = \%statuses;
  }
  return $self->{'status_for_kill'};
}

=head2 sleep

  Arg [1]   : int, number of jobs
  Arg [2]   : int, job_limit
  Function  : sleep for an appropriate amount of time given the number
  of jobs over the maximum there is
  Returntype: int the amount of time sleeped for
  Exceptions: none
  Example   : $self->sleep($job_count, $job_limit);

=cut

sub sleep{
  my ($self, $job_number, $job_limit) = @_;

  my $extra_jobs = $job_number - $job_limit;
  my $sleep      = $extra_jobs * $self->sleep_per_job;

  $sleep = $self->max_job_sleep if ($sleep > $self->max_job_sleep);
  $sleep = $self->min_job_sleep if ($sleep < $self->min_job_sleep);

  sleep($sleep);

  return $sleep;
}

=head2 create_lock

  Arg [1]   : none
  Function  : create a string to lock the pipeline database with
  Returntype: string
  Exceptions: none
  Example   : $lock_str = $self->create_lock;

=cut

sub create_lock{
  my ($self) = @_;

  my $host = $self->qualify_hostname(hostname());
  my $user = scalar getpwuid($<);
  my $lock_str = join ":", "$user\@$host", $$, time();

  $self->db->pipeline_lock($lock_str);

  return $lock_str;
}

=head2 delete_lock

  Arg [1]   : none
  Function  : removes entry from meta-table of database 'pipeline.lock'
  Returntype: string
  Exceptions: none
  Example   : $lock_str = $self->delete_lock;

=cut

sub delete_lock {
  my ($self) = @_;

  my $host = $self->qualify_hostname(hostname());
  my $user = scalar getpwuid($<);
  my $lock_str = join ":", "$user\@$host", $$, time();

  my $arg = $self->db->pipeline_unlock();
  return $arg;
}

=head2 qualify_hostname

  Arg [1]   : string, output of Sys::Hostname::hostname
  Function  : produces fully qualified host name
  Returntype: string
  Exceptions: none
  Example   : my $host = $self->qualify_hostname(hostname());

=cut

sub qualify_hostname{
  my ($self, $hostname) = @_;

  my $addr = gethostbyname($hostname);
  my $host = gethostbyaddr($addr, AF_INET);
  return $host;
}

=head2 is_locked

  Arg [1]   : none
  Function  : to establish if the pipeline is locked, ie if there is  lock
  string already present in the database
  Returntype: int
  Exceptions: throws if a lock str is present
  Example   : $self->is_locked

=cut

sub is_locked{
  my ($self) = @_;

  if (my $lock_str = $self->db->pipeline_lock) {
    my($user, $host, $pid, $started) = $lock_str =~ /(\w+)@([^:]+):(\d+):(\d+)/;

    $started = scalar localtime $started;

    my $dbname = $self->db->dbc->dbname;
    my $dbhost = $self->db->dbc->host;

    my $error_str = ("Error: this pipeline appears to be running!\n\n".
                     "\tdb       $dbname\@$dbhost\n".
                     "\tpid      $pid on ".
                     "host $host\n\tstarted  $started\n\n".
                     "The process above must be terminated before this ".
                     "script can be run.\nIf the process does not exist, ".
                     "remove the lock by removing the lock from the ".
                     "pipeline database:\n\ndelete from meta where ".
                     "meta_key = 'pipeline.lock';\n\n\n\n" .
                     "\tYou could also use the -unlock option to remove the lock" .
                     "\n\n\n Thank you !\n\n");

    print STDERR $error_str;
    throw("Can't run RuleManager there may be another rulemanager ".
          "running look in ".$self->db->dbc->dbname." meta table ");
  }
  return 1;
}

=head2 fetch_complete_accumulators

  Arg [1]   : none
  Function  : fetches the analysis of accumulators which have already run
  Returntype: hash ref
  Exceptions: warns if an analysis with input_id ACCUMULATOR doesn't have
  the type accumulator'
  Example   : my %complete_accumulators = %{$self->
                                              fetch_complete_accumulators};

=cut

sub fetch_complete_accumulators{
  my ($self) = @_;

  $self->{'complete_accumulators'} = {};

  my @accumulators = @{$self->stateinfocontainer->fetch_analysis_by_input_id('ACCUMULATOR')};

  foreach my $analysis (@accumulators) {
    if ($analysis->input_id_type eq 'ACCUMULATOR') {
      $self->{'complete_accumulators'}->{$analysis->logic_name} = 1;
    } else {
      warn(" analysis " . $analysis->logic_name . " must have input id " .
           "type ACCUMULATOR");
    }
  }
  return $self->{'complete_accumulators'};
}

=head2 cleanup_waiting_jobs

  Arg [1]   : none
  Function  : ensures any jobs which are sat waiting to be run at the end of
              a pipeline get left unrun
  Returntype:
  Exceptions:
  Example   :

=cut

sub cleanup_waiting_jobs{
  my ($self) = @_;

  my ($a_job) = $self->job_adaptor->fetch_by_Status("CREATED");

  if ($a_job) {
    $a_job->flush_runs($self->job_adaptor);
  } else {
    print STDERR "have no jobs to clean up\n" if ($self->be_verbose);
  }
}

=head2 add_created_jobs_back

  Arg [1]   : none
  Function  : ensures at created by unsubmitted jobs get readded to the
  queuing system
  Returntype: int
  Exceptions: none
  Example   :

=cut

sub add_created_jobs_back{
  my ($self) = @_;
  my @created_jobs = $self->job_adaptor->fetch_by_Status("CREATED");

  foreach my $j (@created_jobs) {
    $j->batch_runRemote;
  }
  return 1;
}

=head2 rules_setup

  Arg [1]   : hashref, keyed on analysis_id of analyses which are to run
  Arg [2]   : hashref keyed on analysis_id of analyses to skip
  Arg [3]   : arrayref of all rules
  Arg [4]   : hashref of all accumulator analyses
  Arg [5]   : hashref of incomplete accumulators
  Function  : to setup the rules array on the basis of specified analyses
              to either run or skip
  Returntype: arrayref
  Exceptions: throws if no rules are produces at the end
  Example   :

=cut

sub rules_setup{
  my ($self, $analyses_to_run, $analyses_to_skip, $all_rules,
     $accumulator_analyses, $incomplete_accumulators) =@_;
  my @rules;
  #print "SETTING UP RULES\n";
  if (keys(%$analyses_to_run)) {
    foreach my $rule (@$all_rules) {
      #print "CHECKING RULE ".$rule->goalAnalysis->logic_name."\n";
      if (exists($analyses_to_run->{$rule->goalAnalysis->dbID})) {
        #print "ADDING RULE\n";
        push (@rules, $rule);
      } elsif ($accumulator_analyses->{$rule->goalAnalysis->logic_name}) {
        $incomplete_accumulators->{$rule->goalAnalysis->logic_name} = 1;
      }
    }
  } elsif (keys(%$analyses_to_skip)) {
    foreach my $rule (@$all_rules) {
      if (!exists($analyses_to_skip->{$rule->goalAnalysis->dbID})) {
        push (@rules, $rule);
      }
    }
  } else {
    @rules = @$all_rules;
  }
  if (scalar(@rules) == 0) {
    throw("Something is wrong with the code or your commandline setup ".
          "rules_setup has returned no rules");
  }
  $self->rules(\@rules);
  return \@rules;
}

=head2 logic_name2dbID

  Arg [1]   : arrayref of Bio::EnsEMBL::Pipeline::Analysis
  Function  : produce a hash keyed on analysis dbID based on array passed
  in
  Returntype: hashref
  Exceptions: none
  Example   :

=cut

sub logic_name2dbID {
  my ($self, $analyses) = @_;
  my %analyses;

  foreach my $ana (@$analyses) {
    if ($ana =~ /^\d+$/) {
      $analyses{$ana} = 1;
    } else {
      my $id ;
      eval {  $id = $self->analysis_adaptor->fetch_by_logic_name($ana)->dbID; }  ;
      if ($@){
      	print STDERR "\n\nERROR: The analysis (logic_name) you've specified does not exist in the db\n"."\n"x10;
      	throw($@) ;
      }
      if ($id) {
        $analyses{$id} = 1;
      } else {
        print STDERR "Could not find analysis $ana\n";
      }
    }
  }
  return \%analyses;
}

=head2 like_logic_name2dbID

  Arg [1]   : arrayref of MySQL LIKE strings
  Function  : produce a hash keyed on analysis dbID based on array passed
  in. Matches analyses based on the patterns provided in the array passed
  in using the MySQL LIKE operation.
  Returntype: hashref
  Exceptions: none
  Example   :

=cut

sub like_logic_name2dbID {
  my ($self, $logic_name_like) = @_;
  my @logic_names;

  foreach my $like_syntax (@$logic_name_like) {

    my $sth = $self->db->dbc->prepare("
              SELECT analysis_id, logic_name FROM analysis
              WHERE logic_name like \"".$like_syntax."\"");
    my $res = $sth->execute;

    if($res eq "0E0") {
      $res = 0;
    }

    print "Using logic_name_like....\n";
    print "For \'".$like_syntax."\' found ".$res." entries in the analysis table\n\n";

    if ($res > 0) {
      print "Will run on the following analyses:\n\n";

      while (my $ref = $sth->fetchrow_hashref) {
        my $indv_logic_name = $ref->{'logic_name'};
        my $indv_analysis_id = $ref->{'analysis_id'};
        print "Logic name: ".$indv_logic_name." (".$indv_analysis_id.")\n";

        if ($indv_analysis_id) {
          push(@logic_names,$indv_logic_name);
        }

        else {
            print "Couldn't find an analysis id for $indv_logic_name!\n";
        }

      }

      print "\n";

    }

    else {
        print "Warning: no analyses found for pattern \'".$like_syntax."\'!!!\n\n";
    }

  }

  return \@logic_names;

}

=head2 input_ids_setup

  Arg [1]   : string, filename pointing file of input_ids to run
  Arg [2]   : string, filename pointing file of input_ids to skip
  Arg [3]   : array ref, array of input_id_types to run
  Arg [4]   : array ref, array of input_id_types to skip
  Function  : prepare the hash of input_ids to use when running
  Returntype: hashref
  Exceptions: throws if the id_hash is empty
  Example   :
  Notes     :both files are expected in the format input_id input_id_type
=cut

sub input_id_setup{
  my ($self, $ids_to_run, $ids_to_skip,
      $types_to_run, $types_to_skip, $starts_from) = @_;
  my $id_hash;

  $self->empty_input_ids;

  if ($ids_to_run) {

    $id_hash = $self->read_id_file($ids_to_run);
  } elsif (@$starts_from) {

    my @analyses;

    foreach my $logic_name(@$starts_from){
      my $analysis = $self->analysis_adaptor->
        fetch_by_logic_name($logic_name);

      push(@analyses, $analysis);
    }
    $id_hash = $self->starts_from_input_ids(\@analyses);
  }elsif(scalar(@$types_to_run)){
    my %id_type_hash;
    foreach my $type(@$types_to_run){
      my $ids = $self->stateinfocontainer
        ->list_input_ids_by_type($type);
      foreach my $id  (@$ids) {
        $id_type_hash{$type}{$id} = 1;
      }
    }
    $id_hash = \%id_type_hash;
  } else {
    print "Getting standard set\n";
    $id_hash = $self->input_ids;
  }

  if ($ids_to_skip) {
    my $skip_id_hash = $self->read_id_file($ids_to_skip);
    foreach my $type (keys(%$skip_id_hash)){
      foreach my $id (keys(%{$skip_id_hash->{$type}})){
        delete($skip_id_hash->{$type}->{$id});
      }
    }
  }

  if(@$types_to_skip){
    my %types_to_skip = map{$_, 1} @$types_to_skip;
    foreach my $type (keys(%$id_hash)){
      if($types_to_skip{$type}){
        delete($id_hash->{$type});
      }
    }
  }

  if(keys(%$id_hash) == 0){
    throw("Something is wrong with the code or the commandline ".
          "input_ids_setup has produced no ids\n");
  }

  $self->input_ids($id_hash);

  return $id_hash;
}

=head2 check_if_done

  Arg [1]   : none
  Function  : check if the pipeline is finished running
  Returntype: int
  Exceptions: none
  Example   :

=cut

sub check_if_done {
  my ($self) = @_;
  my @jobs = $self->job_adaptor->fetch_all;
  my $continue;

 JOB:
  foreach my $job (@jobs) {
    my $status = $job->current_status->status;

    if ($status eq 'KILLED' || $status eq 'SUCCESSFUL' || $status eq 'VOID' || $status eq 'FAIL_NO_RETRY') {
      next JOB;
    } elsif ($status eq 'FAILED' || $status eq 'AWOL') {
      if (!$job->can_retry) {
        next JOB;
      } else {
        return 1;
      }
    } else {
      return 1;
    }
  }

  return 0;
}

=head2 backup_output_directories

  Arg [1]   : list of analyses
  Function  : create backups of analyses output directories in the DEFAULT_OUTPUT_DIR
  Returntype: none
  Exceptions: failure to move directories
  Example   :

=cut

sub backup_output_directories
{
  my ($self, $analyses_to_run) = @_ ;

  #check the default output dir has been set - this will be the backup location
  my $base_output_dir = $DEFAULT_OUTPUT_DIR ;
  if( $DEFAULT_OUTPUT_DIR eq '' )
  {
      delete_lock() ;
      throw( "Directory '" . $DEFAULT_OUTPUT_DIR .
             "' not a valid location for output backup directories. Set DEFAULT_OUTPUT_DIR in BatchQueue.pm." ) ;
  }
  print "Backup operation dir is ".$base_output_dir."\n" ;

  #timestamp for the name
  my ( $sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst ) = localtime( time() ) ;
  my $timestamp = "_".($mon+1)."-".$mday."-".$hour."-".$min ;
  print "Timestamp used is ".$timestamp."\n" ;

  #cycle through the analyses and move the existing directories (if they exist)
  foreach my $dbID (keys %$analyses_to_run)
  {
      my $ana = $self->analysis_adaptor->fetch_by_dbID( $dbID ) ;

      #obtain the current output directory specification
      my $previous_output_dir = $base_output_dir.'/'.$ana->logic_name() ;

      if( -e $previous_output_dir )
      {
          #make the destination backup directory
          my $backup_dir = $base_output_dir . '/' . $ana->logic_name . $timestamp ;
          #do the backup
          eval
          {
              system( "mv ".$previous_output_dir." ".$backup_dir ) ;
          };
          if( $@ )
          {
              throw( "Failed to move ".$previous_output_dir." to backup dir ".$backup_dir." $@" );
          }
          print "Moved previous run output from ".$previous_output_dir." to backup dir ".$backup_dir."\n" ;
      }
  }
}

sub number_output_dirs {
  my ($self,$arg) = @_ ;
  $self->{number_output_dirs} = $arg if $arg ;
  return $self->{number_output_dirs} ;
}

1;


text:
package kr.ac.kaist.jsaf.compiler

import _root_.java.util.{List => JList}
import kr.ac.kaist.jsaf.ShellParameters
import kr.ac.kaist.jsaf.exceptions.StaticError
import kr.ac.kaist.jsaf.nodes._
import kr.ac.kaist.jsaf.nodes_util.{ NodeFactory => NF }
import kr.ac.kaist.jsaf.nodes_util.{ NodeUtil => NU }
import kr.ac.kaist.jsaf.nodes_util.Span
import kr.ac.kaist.jsaf.scala_src.nodes._
import kr.ac.kaist.jsaf.scala_src.useful.ErrorLog
import kr.ac.kaist.jsaf.scala_src.useful.Lists._
import kr.ac.kaist.jsaf.scala_src.useful.Options._
import kr.ac.kaist.jsaf.useful.HasAt
import kr.ac.kaist.jsaf.Shell

/**
 * Eliminates ambiguities in an AST that can be resolved solely by knowing what
 * kind of entity a name refers to.  This class specifically handles
 * the following:
 *  - Variable/function/label references have unique internal names.
 *  - All name references that are undefined or used incorrectly are
 *    treated as static errors.
 */
class Disambiguator(program: Program, disambiguateOnly: Boolean) extends Walker {
  /* Error handling
   * The signal function collects errors during the disambiguation phase.
   * To collect multiple errors,
   * we should return a dummy value after signaling an error.
   */
  val errors: ErrorLog = new ErrorLog
  def signal(msg:String, hasAt:HasAt) = errors.signal(msg, hasAt)
  def signal(hasAt:HasAt, msg:String) = errors.signal(msg, hasAt)
  def signal(error: StaticError) = errors.signal(error)
  val assignErrors: ErrorLog = new ErrorLog
  def assignSignal(msg:String, hasAt:HasAt) = assignErrors.signal(msg, hasAt)

  def getErrors(): JList[StaticError] = toJavaList(errors.errors)

  /* Environment for renaming identifiers. */
  type Env = List[(String, String)]
  val emptyLabel = ("empty", "empty")
  val pred = if (Shell.pred == null) new Predefined(new ShellParameters())
             else Shell.pred
  var env: Env = pred.vars.map(v => (v,v)) ++
                 pred.funs.map(f => (f,f)) ++ List(("alert", "alert"), // alert???
                                                   (NU.internalPrint, NU.internalPrint))
  // The first Env is the label set of an enclosing IterationStatement
  // The second Env is the label set of an enclosing SwitchStatement
  // The third Env is the label set of an enclosing statement
  // The fourth Env is the label set of the current statement
  val emptyLabEnv = (List(), List(), List(), List())
  var labEnv: (Env, Env, Env, Env) = emptyLabEnv
  val thisName = "this"
  val argName = "arguments"

  /* 15.1.4 Constructor Properties of the Global Object
   * Object, Function, Array, String, Boolean, Number, Date, RegExp, Error,
   * EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError
   */
  def addEnv(name: String, newid: Id): Unit = toOption(newid.getUniqueName) match {
    case None => signal("Identifier " + name + " is not bound.", newid)
    case Some(uniq) => env = (name, uniq)::env
  }
  def addEnv(id: Id, newid: Id): Unit = toOption(newid.getUniqueName) match {
    case None => signal("Identifier " + id.getText + " is not bound.", id)
    case Some(uniq) => env = (id.getText, uniq)::env
  }
  def addEnv(newid: Id): Unit = toOption(newid.getUniqueName) match {
    case None => signal("Identifier " + newid.getText + " is not bound.", newid)
    case Some(uniq) => env = (newid.getText, uniq)::env
  }
  def addLEnv(id: Id, newid: Id): Unit = toOption(newid.getUniqueName) match {
    case None => signal("Identifier " + id.getText + " is not bound.", id)
    case Some(uniq) =>
      labEnv = (labEnv._1, labEnv._2, labEnv._4++labEnv._3, (id.getText, uniq)::labEnv._4)
  }
  def setLEnvCur(lab: (String, String)) =
    labEnv = (labEnv._1, labEnv._2, labEnv._4++labEnv._3, List(lab))
  def setLEnv(n:AbstractNode) = {
    val oldLEnv = labEnv
    labEnv = (labEnv._1, labEnv._2, labEnv._4++labEnv._3, List())
    oldLEnv
  }
  def resetLEnv(lenv: (Env, Env, Env, Env)) = labEnv = lenv

  def getEnvNoCheck(id: Id): String = {
    val name = id.getText
    env.find(p => p._1.equals(name)) match {
      case Some((_, uniq)) => uniq
      case None =>
        val new_name = newId(id).getUniqueName.get
        env = (name, new_name)::env
        new_name
    }
  }

  def getEnvCheck(id: Id): String = {
    val name = id.getText
    env.find(p => p._1.equals(name)) match {
      case Some((_, uniq)) => uniq
      case None =>
        if (!inWith && disambiguateOnly)
          assignSignal("Identifier " + id.getText + " is not bound.", id)
        name
    }
  }

  def inEnv(id: Id): Boolean = {
    val name = id.getText
    env.find(p => p._1.equals(name)) match {
      case Some(_) => true
      case None => false
    }
  }
  def setEnv(envs: (Env, (Env,Env,Env,Env))) =
    { env = envs._1; labEnv = envs._2 }

  def newId(span: Span, n: String) =
    SId(NF.makeSpanInfo(span), n, Some(n), false)
  def newId(id: Id): Id = id match {
    case SId(info, text, _, _) =>
      if (toplevel) SId(info, text, Some(text), false)
      else SId(info, text, Some(NU.freshName(text)), false)
  }
  def newId(id: Id, uniq: String): Id = id match {
    case SId(info, text, _, _) => SId(info, text, Some(uniq), false)
  }
  def newLabel(label: Label): Label = label match {
    case SLabel(info, id) => SLabel(info, newId(id))
  }
  def newLabel(label: Label, uniq: String): Label = label match {
    case SLabel(info, id) => SLabel(info, newId(id, uniq))
  }
  def newPropId(id: Id) = id match {
    case SId(info, text, _, _) =>
      SPropId(info, SId(info, text, Some(text), false))
  }

  def signalDataAccProp(name: String, n: Member) =
    signal("ObjectLiteral may not have a data property and an accessor property with the same name. \"" + name + "\"", n)
  def signalGetProp(name: String, n: Member) =
    signal("ObjectLiteral may not have multiple getter properties with the same name. \"" + name + "\"", n)
  def signalSetProp(name: String, n: Member) =
    signal("ObjectLiteral may not have multiple setter properties with the same name. \"" + name + "\"", n)

  def checkDuplicatedProperty(members: List[Member]) = {
    var member1Str: String = ""
    var member2Str: String = ""
    for(member1 <- members) {
      member1Str = NU.member2Str(member1)
      for(member2 <- members if member1.ne(member2)) {
        member2Str = NU.member2Str(member2)
        if (member1Str.equals(member2Str)) (member1, member2) match {
          case (SField(_,_,_), SGetProp(_,_,_)) =>
            signalDataAccProp(member1Str, member2)
          case (SField(_,_,_), SSetProp(_,_,_)) =>
            signalDataAccProp(member1Str, member2)
          case (SGetProp(_,_,_), SField(_,_,_)) =>
            signalDataAccProp(member1Str, member2)
          case (SSetProp(_,_,_), SField(_,_,_)) =>
            signalDataAccProp(member1Str, member2)
          case (SGetProp(_,_,_), SGetProp(_,_,_)) =>
            signalGetProp(member1Str, member2)
          case (SSetProp(_,_,_), SSetProp(_,_,_)) =>
            signalSetProp(member1Str, member2)
          case _ =>
        }}}
  }

  /* The main entry function */
  def doit() = {
    val result = NU.simplifyWalker.walk(walk(program).asInstanceOf[Program])
    if (!hasAssign) for (e <- assignErrors.errors) signal(e)
    result
  }

  var toplevel = false
  /* IterationStatement: DoWhile, While, For, ForIn */
  var inIterator = false
  var inSwitch = false
  var inFunctionBody = false
  var inWith = false
  var hasAssign = false
  def isAssignOp(op: Op) = op match {
    case SOp(_, text) => text.equals("++") || text.equals("--")
  }
  def mkInIterator() = {
    inIterator = true
    if (labEnv._4.isEmpty) setLEnvCur(emptyLabel)
    labEnv = (labEnv._4++labEnv._1, labEnv._2, labEnv._3, labEnv._4)
  }
  def mkInSwitch()   = {
    inSwitch   = true
    if (labEnv._4.isEmpty) setLEnvCur(emptyLabel)
    labEnv = (labEnv._1, labEnv._4++labEnv._2, labEnv._3, labEnv._4)
  }
  def functional(span: Span, name: Id, params: List[Id], fds: List[FunDecl],
                 vds: List[VarDecl], body: SourceElements) = {
    val old_toplevel = toplevel
    toplevel = false
    labEnv = emptyLabEnv
    addEnv(argName, newId(newId(span, argName)))
    val pairs_params = params.map(p => (p, newId(p)))
    pairs_params.foreach(p => addEnv(p._1, p._2))
    fds.foreach(fd => addEnv(fd.getFtn.getName, newId(fd.getFtn.getName)))
    val new_vds = vds.foldLeft(List[VarDecl]())((vds, vd) => vd match {
        case SVarDecl(info, id, _, strict) => params.find(p => p.getText.equals(id.getText)) match {
          case None =>
            val new_id = newId(id)
            addEnv(id, new_id)
            vds:+SVarDecl(info, new_id, None, strict)
          case _ => vds
        }})
    val new_fds = fds.map(walk).asInstanceOf[List[FunDecl]]
    val oldInFunctionBody = inFunctionBody
    inFunctionBody = true
    val new_body = body match {
      case SSourceElements(i, stmts, strict) =>
        SSourceElements(i, stmts.map(walk).asInstanceOf[List[SourceElement]], strict)
    }
    inFunctionBody = oldInFunctionBody
    toplevel = old_toplevel
    SFunctional(new_fds, new_vds, new_body, name, pairs_params.map(p => p._2))
  }

  override def walk(node: Any): Any = node match {
    case SProgram(info, STopLevel(fds, vds, body)) =>
      fds.foreach(fd => addEnv(fd.getFtn.getName, newId(fd.getInfo.getSpan, fd.getFtn.getName.getText)))
      val new_vds = vds.map(p => p match {
          case SVarDecl(i, id, _, strict) =>
            val new_id = newId(i.getSpan, id.getText)
            addEnv(id, new_id)
            SVarDecl(info, new_id, None, strict)})
      val new_fds = fds.map(walk).asInstanceOf[List[FunDecl]]
      toplevel = true
      SProgram(info,
               STopLevel(new_fds,
                         new_vds,
                         body.map(walk).asInstanceOf[List[SourceElements]]))

    case SSourceElements(info, stmts, strict) =>
      SSourceElements(info,
                      stmts.map(walk).asInstanceOf[List[Stmt]], strict)

    case SFunDecl(info, SFunctional(fds, vds, body, name, params), strict) =>
      val old_env = (env, labEnv)
      val new_name = newId(name, getEnvNoCheck(name))
      val result = SFunDecl(info,
                            functional(info.getSpan, new_name, params, fds, vds, body), strict)
      setEnv(old_env._1, old_env._2)
      result

    case SFunExpr(info, SFunctional(fds, vds, body, name, params)) =>
      val old_env = (env, labEnv)
      val old_toplevel = toplevel
      toplevel = false
      val new_name = newId(name)
      addEnv(name, new_name)
      val result = SFunExpr(info,
                            functional(info.getSpan, new_name, params, fds, vds, body))
      setEnv(old_env)
      toplevel = old_toplevel
      result
    case SGetProp(info, prop, SFunctional(fds, vds, body, name, params)) =>
      val old_env = (env, labEnv)
      val new_prop = newPropId(name)
      val new_name = new_prop.getId
      val result = SGetProp(info, new_prop,
                            functional(info.getSpan, new_name, params, fds, vds, body))
      setEnv(old_env)
      result
    case SSetProp(info, prop, SFunctional(fds, vds, body, name, params)) =>
      val old_env = (env, labEnv)
      val new_prop = newPropId(name)
      val new_name = new_prop.getId
      val result = SSetProp(info, new_prop,
                            functional(info.getSpan, new_name, params, fds, vds, body))
      setEnv(old_env)
      result

    /* 12.8 The break Statement
     * A program is considered syntactically incorrect if either of the following is true:
     *  - The program contains a break statement without the optional Identifier,
     *    which is not nested, directly or indirectly (but not crossing function boundaries),
     *    within an IterationStatement or a SwitchStatement.
     *  - The program contains a break statement with the optional Identifier,
     *    where Identifier does not appear in the label set of an enclosing
     *    (but not crossing function boundaries) Statement.
     */
    case br@SBreak(info, target) =>
      val new_target = target match {
        case Some(label) => labEnv._3.find(p => p._1.equals(label.getId.getText)) match {
          case None => labEnv._2.find(p => p._1.equals(label.getId.getText)) match {
            case None =>
              signal("Break occurs outside of a label.", br)
              return SEmptyStmt(info)
            case Some((_, uniq)) => Some(newLabel(label, uniq))
          }
          case Some((_, uniq)) => Some(newLabel(label, uniq))
        }
        case None =>
          if (!inIterator && !inSwitch) {
            signal("Break occurs outside of an iterator or a switch.", br)
            return SEmptyStmt(info)
          } else None
      }
      SBreak(info, new_target)

    case SCatch(info, id, body) =>
      val old_toplevel = toplevel
      toplevel = false
      val old_env = (env, labEnv)
      val new_id = newId(id)
      addEnv(id, new_id)
      setLEnv(node.asInstanceOf[AbstractNode])
      val result = SCatch(info, new_id, walk(body).asInstanceOf[List[Stmt]])
      setEnv(old_env)
      toplevel = old_toplevel
      result
    /* 12.7 The continue Statement
     * A program is considered syntactically incorrect if either of the following is true:
     *  - The program contains a continue statement without the optional Identifier,
     *    which is not nested, directly or indirectly (but not crossing function boundaries),
     *    within an IterationStatement.
     *  - The program contains a continue statement with the optional Identifier,
     *    where Identifier does not appear in the label set of an enclosing
     *    (but not crossing function boundaries) IterationStatement.
     */
    case c@SContinue(info, target) =>
      if (!inIterator) {
        signal("Continue occurs outside of an iterator.", c);
        return SEmptyStmt(info)
      } else {
        val new_target = target match {
          case Some(label) => labEnv._1.find(p => p._1.equals(label.getId.getText)) match {
            case None =>
              signal("Continue occurs outside of a label.", c)
              return SEmptyStmt(info)
            case Some((_, uniq)) => Some(newLabel(label, uniq))
          }
          case None => None
        }
        SContinue(info, new_target)
      }
    case _:DoWhile =>
      val old_env = (env, labEnv)
      val oldInIterator = inIterator
      mkInIterator
      val result = super.walk(node)
      inIterator = oldInIterator
      setEnv(old_env)
      result
    case _:For =>
      val old_env = (env, labEnv)
      val oldInIterator = inIterator
      mkInIterator
      val result = super.walk(node)
      inIterator = oldInIterator
      val newEnv = env
      setEnv(old_env)
      env = newEnv
      result
    case _:ForIn =>
      val old_env = (env, labEnv)
      hasAssign = true
      val oldInIterator = inIterator
      mkInIterator
      val result = super.walk(node)
      inIterator = oldInIterator
      val newEnv = env
      setEnv(old_env)
      env = newEnv
      result
    case fv:ForVar =>
      signal("ForVar should be replaced by the hoister.", fv)
    case fv:ForVarIn =>
      signal("ForVarIn should be replaced by the hoister.", fv)
    case ls@SLabelStmt(info, label@SLabel(_,SId(_,name,_,_)), stmt) =>
      labEnv._4.find(p => p._1.equals(name)) match {
        case Some(_) =>
          signal("Multiple declarations of the label: " + name + ".", ls)
          ls
        case None =>
          val old_env = (env, labEnv)
          val new_label = newLabel(label)
          addLEnv(label.getId, new_label.getId)
          val result = SLabelStmt(info, new_label, walk(stmt).asInstanceOf[Stmt])
          setEnv(old_env)
          result
      }

    /* 12.9 The return Statement
     * An ECMAScript program is considered syntactically incorrect if it contains
     * a return statement that is not within a FunctionBody.
     */
    case rt@SReturn(info, expr) =>
      if (!inFunctionBody)
        signal("Return occurs outside of a function body.", rt)
      val oldLEnv = setLEnv(node.asInstanceOf[AbstractNode])
      val result = super.walk(rt)
      resetLEnv(oldLEnv)
      result

    case _:Switch =>
      val old_env = (env, labEnv)
      val oldInSwitch = inSwitch
      mkInSwitch
      val result = super.walk(node)
      inSwitch = oldInSwitch
      setEnv(old_env)
      result
    case SVarRef(info, id) => SVarRef(info, newId(id, getEnvCheck(id)))
    case vs:VarStmt => signal("VarStmt should be replaced by the hoister.", vs)
    case _:While =>
      val old_env = (env, labEnv)
      val oldInIterator = inIterator
      mkInIterator
      val result = super.walk(node)
      inIterator = oldInIterator
      setEnv(old_env)
      result
    case SObjectExpr(info, members) =>
      checkDuplicatedProperty(members)
      val oldLEnv = setLEnv(node.asInstanceOf[AbstractNode])
      val result = super.walk(node)
      resetLEnv(oldLEnv)
      result
    case _:With =>
      val old_env = (env, labEnv)
      val oldInWith = inWith
      inWith = true
      setLEnv(node.asInstanceOf[AbstractNode])
      val result = super.walk(node)
      inWith = oldInWith
      setEnv(old_env)
      result
    case SAssignOpApp(info, SParenthesized(_, lhs), op, right) if lhs.isInstanceOf[LHS] =>
      val oldLEnv = setLEnv(node.asInstanceOf[AbstractNode])
      val result = walk(SAssignOpApp(info, lhs.asInstanceOf[LHS], op, right))
      resetLEnv(oldLEnv)
      result
    case SAssignOpApp(info, SVarRef(_, id), op, right) =>
      hasAssign = true
      val oldLEnv = setLEnv(node.asInstanceOf[AbstractNode])
      val old_toplevel = toplevel
      val new_id = if (!inEnv(id)) {
                     toplevel = true
                     newId(id)
                   } else newId(id, getEnvNoCheck(id))
      toplevel = old_toplevel
      val result = SAssignOpApp(info, SVarRef(info, new_id),
                                op, walk(right).asInstanceOf[Expr])
      resetLEnv(oldLEnv)
      if (!inEnv(id)) {
        toplevel = true
        addEnv(id, newId(id))
        toplevel = old_toplevel
      }
      result
    case _:AssignOpApp =>
      hasAssign = true
      val oldLEnv = setLEnv(node.asInstanceOf[AbstractNode])
      val result = super.walk(node)
      resetLEnv(oldLEnv)
      result
    case _:UnaryAssignOpApp =>
      hasAssign = true
      val oldLEnv = setLEnv(node.asInstanceOf[AbstractNode])
      val result = super.walk(node)
      resetLEnv(oldLEnv)
      result
    case n:PrefixOpApp =>
      if (isAssignOp(n.getOp)) hasAssign = true
      val oldLEnv = setLEnv(node.asInstanceOf[AbstractNode])
      val result = super.walk(node)
      resetLEnv(oldLEnv)
      result
    case SRegularExpression(info, body, flags) => {
      val regexp = "RegExp"
      SNew(info, SFunApp(info, SVarRef(info, SId(info, regexp, Some(regexp), false)),
                         List(SStringLiteral(info, "\"", NU.escape(body)),
                              SStringLiteral(info, "\"", flags))))
    }
    case _: Comment => node
    case _: AbstractNode =>
      val oldLEnv = setLEnv(node.asInstanceOf[AbstractNode])
      val result = super.walk(node)
      resetLEnv(oldLEnv)
      result
    case _ => super.walk(node)
  }
}

redpajama_set_name: RedPajamaGithub


text:
#ifndef AVOGADRO_RENDERING_TEXTRENDERSTRATEGY_H
#define AVOGADRO_RENDERING_TEXTRENDERSTRATEGY_H

#include "avogadrorenderingexport.h"

#include <avogadro/core/vector.h>

#include <string>

namespace Avogadro {
namespace Rendering {
class TextProperties;

/**
 * @class TextRenderStrategy textrenderstrategy.h
 * <avogadro/rendering/textrenderstrategy.h>
 * @brief The TextRenderStrategy class defines an interface for generating
 * text images.
 */
class AVOGADRORENDERING_EXPORT TextRenderStrategy
{
public:
  TextRenderStrategy();
  virtual ~TextRenderStrategy();

  /**
   * Copy the current TextRenderStrategy implementation into an new object.
   */
  virtual TextRenderStrategy* newInstance() const = 0;

  /**
   * @brief Calculate a bounding box.
   * @param string The text.
   * @param tprop The properties.
   * @param bbox The result in pixels (left, right, top, bottom).
   */
  virtual void boundingBox(const std::string &string,
                           const TextProperties &tprop,
                           int bbox[4]) const = 0;

  /**
   * @brief render Render the string.
   * @param string The text.
   * @param tprop The properties.
   * @param buffer The target. Must be dims[0]*dims[1]*4
   * bytes. The buffer will be filled with RGBA image data, with the top
   * scan row at the beginning.
   * @param dims Dimensions in pixels of the target buffer.
   */
  virtual void render(const std::string &string,
                      const TextProperties &tprop,
                      unsigned char *buffer,
                      const Vector2i &dims) const = 0;
};

} // namespace Rendering
} // namespace Avogadro

#endif // AVOGADRO_RENDERING_TEXTRENDERSTRATEGY_H


text:
. build.common

# Build riscv-tests
OUTPUT_FILE=$OUTPUT_PATH/riscv-tests.log
echo "Building riscv-tests... (writing output to $OUTPUT_FILE)"
cd $RISCV
rm -rf build-tests
mkdir -p build-tests
cd build-tests
../../riscv-tests/configure --prefix=$RISCV/riscv64-unknown-elf &> $OUTPUT_FILE
make -j$JOBS &>> $OUTPUT_FILE
make install &>> $OUTPUT_FILE

cd $STARTINGDIR

echo ""
echo "RV64G riscv-tests compiled successfully."


text:
// Copyright 2009 the Sputnik authors.  All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/**
 * @name: S15.7.3.2_A4;
 * @section: 15.7.3.2;
 * @assertion: Number.MAX_VALUE has the attribute DontEnum;
 * @description: Checking if enumerating Number.MAX_VALUE fails;
*/

//CHECK#1
for(var x in Number) {
  if(x === "MAX_VALUE") {
    $ERROR('#1: Number.MAX_VALUE has the attribute DontEnum');
  }
}

if (Number.propertyIsEnumerable('MAX_VALUE')) {
  $ERROR('#2: Number.MAX_VALUE has the attribute DontEnum');
}


text:
<?xml version="1.0" encoding="UTF-8"?>

<udhr iso639-3='toj' xml:lang='toj' key='toj' n='Tojolabal' xmlns="http://www.unhchr.ch/udhr">
   <title>SPUKJEL YI'B'ANAL JA JAS OJ B'OB'</title>
   <note>
      <para>K'ULAXUK</para>
      <para>Tulub'al sok alub'al yuj ja niwak tsomjel ja chonab' jumasa sta'osb'aj, tiwax tax b'a sju'unil yajtab'il lajun tajb'e' sok juk lajune' (217) A (III) sb'a lajune yajtab' disiembre sb'a 1948.</para>
   </note>
   <preamble>
      <title>STULULAB'IL</title>
      <para>Wax na'xi ja sijpanu'b'ali, ja lekilali sok ja lamaneli ja b'a lu'um k'inali tini wax tax-a ja yajni wax na'ji ja junotikxta-i ki'b'analtik ja b'a lu'um k'inali.</para>
      <para>Wax na'xi ja yajni mi' junxta wa la iljitiki, sok ja mi' lek wa la iljitiki tini wax k'e'a ja niwan tsatsal k'umal-a, ja iti ja'ni sb'a oj na'xuk k'inal ke mi lekuk ja oj kijnajb'atiki; ja'yuj alub'al ke ja jas wax k'anxi-i ja b'a lu'um k'inali ja'ni sb'a mi oj ajyuk xiwel sok wokolal tixa-a oj b'ob' kaltik ja jas wax k'anxi sok ja tuk tukil ja jas wax k'uaxi-i.</para>
      <para>Wax na'xi ke jel t'ilan ja jas wax b'ob' k'ulaxuki oj ajyuk sju'unil b'a mi' t'ilan t'enub'aluk ja swinkil ja lu'um k'inali oj sle' oj sjome' ja jas wax smaka yoki, ja jastal ixtalajel sok ja tuk wax ilwaniye' ja tantik ma'tik ay scholi.</para>
      <para>Jel t'ilan ja tuktukil niwak chonab' jumasa ja b'a lu'um k'inali oj skoltasb'aje sok jel ni t'ilan oj yil sb'aje lek.</para>
      <para>Wax na'xi ja tuktukil niwak chonab'staunesb'aje-i yaluneje ja b'a ju'un tulan yujle-i, tini wax yala-a ja jas oj b'ob' k'ulaxuki, ja jastal jna'ulab'iltik, ja jastalotiki sok ja junxtaotik winik sok ixuk, cha yaluneje' jastal oj taxuk ja lekilali ja b'a jas wax k'anxi-i sok ja jas wax k'anxi oj k'ulaxuki.</para>
      <para>Wax na'xi ja tuktukil Estado b'a yaunesb'aj sok ja tsomjel b'a chonab' jumasa, oj skoltsb'aje ja b'a spetsanal snaulab'ile sok ja jas wax b'ob' k'ultiki sok ja tuktukil ja jas wax yala jas k'ujol ja swinkil ja lu'um k'inali.</para>
      <para>Ja niwan tsomjeli wax yala cha wax spuktes yi'b'anal ja jas oj b'ob' k'ulaxuki ja'yuj ja tuktukil chonab'i sok ja niwak chonab'i jel t'ilan oj sk'ujoluke, ja'yuj cho majkil ja jujune swinkil ja lu'um k'inali sok ja snajtsil b'aye-i ja matik ay scholi jel t'ilan oj sje'e ja sneb'jel ja ju'juni ja jastal lek oj kilb'ajtik jpetsaniltik, ja jas wax b'ob' k'ulaxuki sok ja sijpanub'ali. Jel t'ilan oj yil-e jastal oj k'otuk ja jas wax yala ja ju'un iti ja niwak chonab' jumasa b'a'ytiki sok ja tuktukil niwak chonab' ja b'a lu'um k'inali, ja'chni jel t'ilan oj ilxuk ta wax k'ot meran ja jas wax yala ja ju'un iti ja b'as petsanal ja niwak chonab' jumasa ma'tik ochel ja b'a niwan tsomjeli sokni ja b'a lu'um k'inal b'a'ytik ja ke'ntiki.</para>
   </preamble>

      <title>Artikulo 1.</title>
      <para>Spetsanal ja swinkil ja lu'um k'inali junxta wax jul schonjel, sok ja sijpanub'ali, ja yuj ojni b'ob' sk'u'luk ja jas sk'ana-i ja b'as lekilali, ja yuj ja ay sk'ujoli sok ay spensari t'ilan oj yilsb'aje lek sok ja smoj jumasa.</para>

      <title>Artikulo 2.</title>
      <para>Spetsanal ja swinkil ja lu'um k'inali, ojni b'ob' sk'uluk ja jas wax sk'ana-i sok sijpanub'alni ja jastal wax yala ja b'a ju'un iti, mini ma' mas lek oj iljuk a'ma tuktukiluk ja yelawi, sok a'ma winikuk ma ixuk, cha a'nima tuktukiluk ja sk'umali, cha ja'chni ja jas wax sk'ani, sok ja spensari, ma jas tuk, ja b'a niwan chonab' b'a'yi sok ja tsome b'a kulani, cha ja'chni a'mani me'y lek stak'in sok a'nima chikan jastal jul schonjel.</para>
      <para>Cha ja'chni spetsanal ja swinkil ja lu'um k'inali junxtani oj ilxuka a'ma tuktukiluk ja spensari sok ja sju'unil ja jas oj b'ob' sk'uluki, ma ama tuktukiluk niwak chonab' ja b'a'yi, cha a'ma jauk ja b'a slujmal b'a kulani, cha a'nima jun niwan chonab' sijpanub'alxa ma jun slujmal b'a ay k'eluman ke titoni ay b'a sk'ab' b'a jun niwan chonab', ma oj kaltik jun niwan chonab' b'a mito sijpanub'aluk.</para>

      <title>Artikulo 3.</title>
      <para>Yi'b'anal ja swinkil ja lu'um k'inali ojni b'ob' sk'an sak'anil-a, cha ja'chni ja sijpajeli sok cha ja'chni cho majkil ja b'a mi jas oj utjuki.</para>

      <title>Artikulo 4.</title>
      <para>Mixani jun swinkil ja lu'um k'inali oj b'ob' ajyuk mosoil, sok mixani ma oj b'ob' ixtalajuk-a ja'yuj misani ma oj b'ob' sk'eb'e ja yateli, ja'ch wax yala ja ju'un iti.</para>

      <title>Artikulo 5.</title>
      <para>Mixani ma oj b'ob' ixtalajuk, mixani utjel sok cha mixani ma'k'jel.</para>

      <title>Artikulo 6.</title>
      <para>Yi'b'anal ja aswinkil ja lu'um k'inlai, t'ilan oj najusb'aj ja b'a oj och b'e ja jastalni-i.</para>

      <title>Artikulo 7.</title>
      <para>Ki'b'analtik junotikxta ja b'a yojol ja leyi, cha ja'chni junxtani oj ajyuk jk'eljeltik sok jkoltajeltik yuja leyi. Petsanaltik ay jkoltajeltik yuja leyi ja ta tuk wala iljitiki, cha ja'chni ja ta ay k'ejnajeltiki, ja'ch wax yala ja ju'un iti.</para>

      <title>Artikulo 8.</title>
      <para>Yi'b'anal ja swinkil ja lu'um k'inali ja'ni oj b'ob' skoltasb'aj sok ja leyi, ja b'a stisat ja tantik jnal ja ma was na'a sk'eljel ja lekilali ja ta ayk'a ixtalajeli ja jas wax yala ja b'a sju'unil ja leyi.</para>

      <title>Artikulo 9.</title>
      <para>Mini ma' lomxa oj yamjuk, mini ma' oj lutjuk me'y smul, cha mini oj b'ob' nutsjuk ja b'a lu'um b'a kulani.</para>

      <title>Artikulo 10.</title>
      <para>Spetsanal ja swinkil ja lu'um k'inali, t'ilani oj maklajuk yuj ja ma' wa sk'ela ja lekilali ja b'a oj aljuyab'i ja jas a'telil yujni oj sk'uluki, ma oj jk'eljuk jasunka ja smul wax le'jiyi-i.</para>

      <title>Artikulo 11.</title>
      <orderedlist>
         <listitem>
            <para>Spetsanal ja swinkil ja lu'um k'inali, yajni wax le'jiyi smul ojni b'ob' yal ke mi meranuka ja yajni mitoni xchiknaji ta meran ja ay smuli ja'ni oj makunuk yuj ja ley ts'ibjb'anub'ali b'a oj yal ta meran ma miranuk ja mulal leub'alyi-i.</para>
         </listitem>
         <listitem>
            <para>Mini oj b'ob' alxuk ts mulal ja jas wax k'ulaxi-i ja ta minik'a mulaluki, ja'ch wax yala ja sley ja niwak chonab'i, sok ja tuktukil niwak chonab'i, cha mini oj b'ob' lexuk mas tsats ja mulali ja ta minik'a ja'ch k'ulaxi-i.</para>
         </listitem>
      </orderedlist>

      <title>Artikulo 12.</title>
      <para>Mini ma lomta oj b'ob' sch'iksb'a ja b'a yoj jne'b'ailtiki, mini ja b'a yoj jnajtiki, cha mini ma' jas oj b'ob' yalkabtik-a ja b'a oj jomuk ka k'ujulaltiki ma ja jpensantiki. Yi'b'analni-a ja swinkil ja lu'um k'inali ojni b'ob' skoltasb'aj sok ja leyi ja ta ayni wax sch'ikasb'aj ja b'a yoj jneb'ailtiki.</para>

      <title>Artikulo 13.</title>
      <orderedlist>
         <listitem>
            <para>Yi'b'anal ja swinkil ja lu'um k'inali, ojni b'ob' b'ejyuek-a, ja'chni oj b'ob' stsa-e ja b'a oj yaj kulan jas naji ja ni chikan ja b'a Estadoil b'a'yi.</para>
         </listitem>
         <listitem>
            <para>Yib'anal ja swinkil ja lu'um k'inali, ojni b'ob' waj-ek'a b'a tuktukil niwak chonab', cha ojni b'ob' kumxuk ja b'a niwan chonab' b'a kulani.</para>
         </listitem>
      </orderedlist>

      <title>Artikulo 14.</title>
      <orderedlist>
         <listitem>
            <para>Ay-k'a ma' wax iji spatik yuja ma' ay scholi ja b'a niwan chonab' b'a kulani ojini b'ob' sle' b'a oj ajyuk b'a pilan niwan chonab'.</para>
         </listitem>
         <listitem>
            <para>Mini jun ma' ay schol, cha mini ka tuktukil niwak chonab' stausb'a oj b'ob' yal oj kumxukotik ja ta yujnik'a mix k'anatiki.</para>
         </listitem>
      </orderedlist>

      <title>Artikulo 15.</title>
      <orderedlist>
         <listitem>
            <para>Spetsanal ja swinkil ja lu'um k'inlai, ojni b'ob' yal b'a niwanil chonab'il oj ajyuk kulan-a.</para>
         </listitem>
         <listitem>
            <para>Mini ma oj b'ob' nutsjuk ja b'a niwan chonab' b'a kulani, cha mini t'iulan oj t'enjuk b'a oj wajuk b'a pilan niwan chonab'.</para>
         </listitem>
      </orderedlist>

      <title>Artikulo 16.</title>
      <orderedlist>
         <listitem>
            <para>Ja winik sok ja ixuki yajni julta sk'ujule, ojni b'ob' nupanuke-a ja b'a oj sle-e ja sne'b'aile-i a'ma tuktukil ja yelawe-i, sok a'ma tuktukiluk ja schonab'il b'a kulane-i, cha a'ma pilan pilanuk ja jas wax sk'uane-i, yajni nupanelexa junxtani oj iljuke yuj ja leyi, cha ja'chni ja ta sijpasb'aje-i.i</para>
         </listitem>
         <listitem>
            <para>Kechani ja ma' sk'el sat sb'aje-i yenleni oj yal-e-a ta oj nu panuke ma mi oj nupanuke.</para>
         </listitem>
         <listitem>
            <para>Ja jne'b'ailtiki ja'ni mas t'ilan b'a jun yojol tsomjel ma b'a jun yoj komon, ojni b'ob' k'eljuke yuj ja komon-a ma ja' Estado b'a kulane-i.</para>
         </listitem>
      </orderedlist>

      <title>Artikulo 17.</title>
      <orderedlist>
         <listitem>
            <para>Spetsanal ja swinkil ja lu'um k'inali, ojni b'ob' ajyuk sjasb'aj b'a stu'ch'il ma ja'ch komon.</para>
         </listitem>
         <listitem>
            <para>Mini ma lomxta oj japjuyi-a jas jasb'aji.</para>
         </listitem>
      </orderedlist>

      <title>Artikulo 18.</title>
      <para>Spetsanal ja swinkil ja lu'um k'inali, ojni b'ob' sk'u'luke ja jas wax sk'anawe-i, sok ja jas wax sk'uane-i; ja b'a ju'un iti wax yala oj b'ob' stukb'es ma oj sjeltes ja jas wax sk'uani, cha ja'chni ojni b'ob' sje'e ja jas wax sk'uani a'ma stuch'iluk ma ja'ch tsoman. A'ma tiuk b'a snaj ma ti' b'a wax ajyi stsomjele-i jani oj b'ob' sje'e ja jas wax sk'uane-i sok ja jastal wax sk'uane-i.</para>

      <title>Artikulo 19.</title>
      <para>Spetsanal ja swinkil ja lu'um k'inali, ojni b'ob' yal-e ja jasunka ja spensare-i sok mini oj b'ob' ixtalajuk yuj ja jasunka wax yala-i ma jasunka spensari; cha ja'chni oj b'ob' sle-e sok oj b'ob' smakla ja spensar ja smoj jumasa-i, cha ja'chni ojni b'ob'o spuktes ja jas wax sk'uani sok jas pensari, a'ma chikan b'a'a.</para>

      <title>Artikulo 20.</title>
      <orderedlist>
         <listitem>
            <para>Spetsanal ja swinkil ja lu'um k'inali, ojini b'ob' stsomsb'aje-a cha ja'chni oj b'ob' stasb'aje.</para>
         </listitem>
         <listitem>
            <para>Mi ma' t'ilan t'enub'aluk oj ochuk b'a jun tsomjel.</para>
         </listitem>
      </orderedlist>

      <title>Artikulo 21.</title>
      <orderedlist>
         <listitem>
            <para>Spetsanal ja swinkil ja lu'um k'inali, ojni b'ob' yal jastal oj lexuk ja ma oj och sok schol ja b'a jun niwan chonab'i, a'mani ye'ntani-a ma a'nima tsaub'al oj eluk ja ma oj waj yal ja jastal oj ajyuk ja ma'och sok scholi.</para>
         </listitem>
         <listitem>
            <para>Yib'anal ja swinkil ja lu'um k'inali ojni b'ob' syam schol-a jua b'a niwan chonab' b'a kulani.</para>
         </listitem>
         <listitem>
            <para>Yi'b'anal ja ma' ay schol b'a jun niwan choanb'i ja'ni yipunej spetsanal ja swinkil ja chonab' b'a'yi, ja ipanel wax tax ti-i ti wax je'xi ja yajni wax tsa'xi ja ma oj ochsok scholi. Ja tsaumani ye'ntani oj yile machunka wax sk'ana ja ma oj syam scholi.</para>
         </listitem>
      </orderedlist>

      <title>Artikulo 22.</title>
      <para>Spetsanal ja swinkil ja jun tsomjeli ma ja jun komoni ojni sta' slekilal-a ja ta wax koltaji yuj ja yestado ba'yi ma ja'yu ja tuktukil niwak chonab' jumasa-i; ja lekilal wax tax ti-i ja' ni jastal oj ta'tik t'un modo, ja slekilal ja tsomjeltiki ma ja' slekilal ja komontiki ja jastalotikni-i.</para>

      <title>Artikulo 23.</title>
      <orderedlist>
         <listitem>
            <para>Spetsanal ja swinkil ja lu'um k'inali, ojni b'ob' stsa'e ja a'tel ja jas wax sk'ana oj sk'u'luki ja ni sb'a oj ya e'k'uk ja swokoli cha ja'chni oj koltajuk yuj ju'un iti ja ta mi sta-a ja ya'teli.</para>
         </listitem>
         <listitem>
            <para>Spetsanal ja swinkil ja lu'um k'inali, junxtak'a ja ya'teli cha ja'chni junxta oj yi' ja stsakol ja ya'teli.</para>
         </listitem>
         <listitem>
            <para>Yib'anal ja swinkil ja lu'um k'inali, ja ma' wax a'tiji ayni sb'ej oj tupjuk lek ja yateli sb'a oj ya ek'uk ja swokili cha ja'chni ja sne'b'aili, mik'a lek lek x-ekyuj ay ni sb'ej oj koltajuk yuj ja ma' tik ay schol b'a koltaneli.</para>
         </listitem>
         <listitem>
            <para>Spetsanal ja swinkil ja lu'um k'inali, ojni b'ob' ya kulan jun stsomjel ma oj och b'a jun tsomjel sb'a oj skoltasb'aj ja b'a jas wax sk'ana oj sk'uluki.</para>
         </listitem>
      </orderedlist>

      <title>Artikulo 24.</title>
      <para>Yi'b'anal ja swinkil ja lu'um k'inali ojni b'ob' jijluk-a ja b'a ya'teli cha t'ilani oj naxuk janek' ora oj b'ob' a'tijuk, sok ya'ni wax jijli t'ilan lek oj tupjuk.</para>

      <title>Artikulo 25.</title>
      <orderedlist>
         <listitem>
            <para>Spetsanal ja swinkil ja lu'um k'inali ojni b'ob' sle-a ja slekilali ja b'a oj ajyuk lek ja sn'eb'aili ja ni mas t'ilan ja jas oj ya'b'i, ja sk'u'sjasb'aji, ja snaji, sok ja skoltajel ja ta ko' chameli, cha ja'chni ja jastik oj makunuk yuj ja b'a mas lek oj ajyuki, cha ja'chni oj b'ob' sk'an skoltajel ja ta mik'a sta'a yateli, cha jachuk ja ta ay chameli ma mi lekuk ay lek, ma ne'b'axa ay, ma jelxa sk'ujol, cha ojni b'ob' sk'an skoltajel ja ta ay k'a jas ek'sb'aji.</para>
         </listitem>
         <listitem>
            <para>Ja laum ixuk sok ja yali t'ilani oj k'elxuke-a, cha ja'chni sok stalnajele. Yi'b'anal ja yal untik b'a te'y sok snan stati ma mi te'yuk sok-a, t'ilani junxta oj ajyuk sk'eljele-a.</para>
         </listitem>
      </orderedlist>

      <title>Artikulo 26.</title>
      <orderedlist>
         <listitem>
            <para>Spetsanal ja swinkil ja lu'um k'inali, ojni b'ob' sne'b'ju'un-a, ja ne'b'uju'uni mini oj tupxuk-a ja b'a sb'ajtanil ja'b'il man b'a swakil ja'b'il, jaxa juntik'e oxe jab'ili sok ja chane ja'b'il b'a mas tsatsxa ayi ojni b'ob' och kotik jpetsanaltik pe ja'ni chikan ta jne'b'unejtik lek ja'chni wax yala ja ju'un iti.</para>
         </listitem>
         <listitem>
            <para>Ja ne'b'uj ju'uni ja'ni sb'a oj koltanuk ja b'a oj taxuk ja lekilali, cha ja'ni sb'a oj na'tik jastal oj ajyukotik, cha ja'chni ja sb'aj sijpanub'ali, ojni cha b'ob' koltanuk ja jastal oj yilsb'aje ja tuktukil niwak chonab'i sok ja indijena jumasa-i sok ja tsome ma' tuktukil ja jas wax sk'uani, cha ojni koltanuk ja b'a lek oj yilsb'aji sok b'a laman oj ajyuke ja tuktukil niwak chonab'i.</para>
         </listitem>
         <listitem>
            <para>Ja nanl tatal jumasa ojni b'ob' stsa-e ja jas ne'b'uju'unil wax sk'ana oj sna-e ja yuntikile-i.</para>
         </listitem>
      </orderedlist>

      <title>Artikulo 27.</title>
      <orderedlist>
         <listitem>
            <para>Spetsanal ha swinkil ja lu'um k'inali ojni b'ob' stsa-e ja jas wax sk'ana oj sk'uluke ja b'a yoj skomoni, cha ja'chni oj b'ob' och sle'jel ja jas wax k'anxi oj nebxuki b'a oj taxuk ja lekilali.</para>
         </listitem>
         <listitem>
            <para>Spetsananl ja swinkil ja lu'um k'inali, ojni b'ob' koltaxuk yuj ja a'tel wax sk'ulan sok ja spensari, sok jas jasb'aji b'a ye'ni sk'uluneji.</para>
         </listitem>
      </orderedlist>

      <title>Artikulo 28.</title>
      <para>Spetsanal ja swinkil ja lu'um k'inali ojni b'ob' sk'an-a ke oj ajyuk laman yib'anal ja tuktukil niwak chonab'i b'a oj k'ot meran ja jas wax yala ja ju'un iti.</para>

      <title>Artikulo 29.</title>
      <orderedlist>
         <listitem>
            <para>Spetsanal ja swinkil ja lu'um k'inali t'ilani oj ya' ya'tel ja b'a komon b'a'yi, ja'ni yuj ja ti sna-a k'inali.</para>
         </listitem>
         <listitem>
            <para>Ya'ni tixa ay b'a yojol ja jas oj b'ob' sk'u'luki t'ilani oj sk'u'luk ja jas wax yala ja leyi, ja'ni sb'a mi oj och sok k'umal ja smoj jumasa, cha ja'chni b'a lek oj yilsb'aje, yujni ja sb'a oj ajyuk laman sok lek oj yilsb'aje spetsanale ja komon jumasa ma' lajan wax sle-a slekilale-i.</para>
         </listitem>
         <listitem>
            <para>Ja jas wax b'ob' k'u'laxuki, sok ja sijpanub'ali, mi oj b'ob' k'u'laxuk ja ta mi jachukuk ja jastal yaluneje sok ya' oje kulan ja niwak choanb' jumasa staunesb'aje-i.</para>
         </listitem>
      </orderedlist>

      <title>Artikulo 30.</title>
      <para>Ja b'a ju'un iti, wanix yal kab'tik toj ke mini jun Estado, mini jun tsomjel, cha mini jun swinkil ja lu'um k'inali oj ya makunuk b'a slekilal, ma b'a oj ixtalanuk. Ja' yuj jel t'ilan oj na'xuk ja jas oj b'ob' k'ulaxuki, sok ja sijpanub'al wax yala ja b'a ju'un iti.</para>

</udhr>


text:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Wintellect.PowerCollections;

class Tasks
{
    static OrderedBag<Task> tasks = new OrderedBag<Task>();

    static void Main()
    {
        int commandsCount = int.Parse(Console.ReadLine());
        StringBuilder output = new StringBuilder();
        for (int i = 0; i < commandsCount; i++)
        {
            output.Append(ExecuteCommand(Console.ReadLine()));
        }

        Console.Write(output);
    }

    static string ExecuteCommand(string command)
    {
        int indexOfSpace = command.IndexOf(' ');
        if (indexOfSpace == -1)
        {
            if (tasks.Count > 0)
            {
                Task toSolve = tasks.GetFirst();
                tasks.Remove(toSolve);
                return toSolve.Name + Environment.NewLine;
            }
            else
            {
                return "Rest" + Environment.NewLine;
            }
        }
        else // Adding a new task
        {
            int indexOfSecondSpace = command.IndexOf(' ', indexOfSpace + 1);
            int complexity = int.Parse(command.Substring(indexOfSpace + 1, indexOfSecondSpace - indexOfSpace));
            string name = command.Substring(indexOfSecondSpace + 1);
            tasks.Add(new Task(complexity, name));
            return "";
        }
    }
}

class Task : IComparable<Task>
{
    public int Complexity { get; private set; }

    public string Name { get; private set; }

    public Task(int complexity, string name)
    {
        this.Complexity = complexity;
        this.Name = name;
    }

    public int CompareTo(Task other)
    {
        int complexityComparison = this.Complexity.CompareTo(other.Complexity);
        if (complexityComparison != 0)
        {
            return complexityComparison;
        }
        else
        {
            return this.Name.CompareTo(other.Name);
        }
    }
}


text:
FILE(REMOVE_RECURSE
  "CMakeFiles/calc_normals.dir/calc_normals.cc.o"
  "../../../bin/calc_normals.pdb"
  "../../../bin/calc_normals"
)

# Per-language clean rules from dependency scanning.
FOREACH(lang CXX)
  INCLUDE(CMakeFiles/calc_normals.dir/cmake_clean_${lang}.cmake OPTIONAL)
ENDFOREACH(lang)


text:
package com.muzammilpeer.gistapplication;

/**
 * Created by muzammilpeer on 22/07/2015.
 */

import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.view.ViewCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.graphics.Palette;
import android.support.v7.widget.Toolbar;
import android.transition.Slide;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;

public class DetailActivity extends AppCompatActivity {

    private static final String EXTRA_IMAGE = "com.antonioleiva.materializeyourapp.extraImage";
    private static final String EXTRA_TITLE = "com.antonioleiva.materializeyourapp.extraTitle";
    private CollapsingToolbarLayout collapsingToolbarLayout;

    public static void navigate(AppCompatActivity activity, View transitionImage, ViewModel viewModel) {
        Intent intent = new Intent(activity, DetailActivity.class);
        intent.putExtra(EXTRA_IMAGE, viewModel.getImage());
        intent.putExtra(EXTRA_TITLE, viewModel.getText());

        ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, transitionImage, EXTRA_IMAGE);
        ActivityCompat.startActivity(activity, intent, options.toBundle());
    }

    @SuppressWarnings("ConstantConditions")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initActivityTransitions();
        setContentView(R.layout.activity_detail);

        ViewCompat.setTransitionName(findViewById(R.id.app_bar_layout), EXTRA_IMAGE);
        supportPostponeEnterTransition();

        setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        String itemTitle = getIntent().getStringExtra(EXTRA_TITLE);
        collapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
        collapsingToolbarLayout.setTitle(itemTitle);
        collapsingToolbarLayout.setExpandedTitleColor(getResources().getColor(android.R.color.transparent));

        final ImageView image = (ImageView) findViewById(R.id.image);
        Picasso.with(this).load(getIntent().getStringExtra(EXTRA_IMAGE)).into(image, new Callback() {
            @Override
            public void onSuccess() {
                Bitmap bitmap = ((BitmapDrawable) image.getDrawable()).getBitmap();
                Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
                    public void onGenerated(Palette palette) {
                        applyPalette(palette);
                    }
                });
            }

            @Override
            public void onError() {

            }
        });

        TextView title = (TextView) findViewById(R.id.title);
        title.setText(itemTitle);
    }

    private void initActivityTransitions() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Slide transition = new Slide();
            transition.excludeTarget(android.R.id.statusBarBackground, true);
            getWindow().setEnterTransition(transition);
            getWindow().setReturnTransition(transition);
        }
    }

    private void applyPalette(Palette palette) {
        int primaryDark = getResources().getColor(R.color.primary_dark);
        int primary = getResources().getColor(R.color.primary);
        collapsingToolbarLayout.setContentScrimColor(palette.getMutedColor(primary));
        collapsingToolbarLayout.setStatusBarScrimColor(palette.getDarkMutedColor(primaryDark));
        updateBackground((FloatingActionButton) findViewById(R.id.fab), palette);
        supportStartPostponedEnterTransition();
    }

    private void updateBackground(FloatingActionButton fab, Palette palette) {
        int lightVibrantColor = palette.getLightVibrantColor(getResources().getColor(android.R.color.white));
        int vibrantColor = palette.getVibrantColor(getResources().getColor(R.color.accent));

        fab.setRippleColor(lightVibrantColor);
        fab.setBackgroundTintList(ColorStateList.valueOf(vibrantColor));
    }
}


text:
{% load i18n %}

{% trans 'Payment' %}

    {% for payment_method in payment_methods %}

                <input type="radio"
                       name="payment_method"
                       class="update-checkout payment-methods payment-method-type-{{ payment_method.type }}"
                       id="payment-method-{{ payment_method.id }}"
                       {% ifequal payment_method.id selected_payment_method.id  %}checked="checked"{% endifequal %}
                       value="{{payment_method.id}}" />

                {% if payment_method.image %}

                {% endif %}

                {{ payment_method.name }}

                {{ payment_method.description|safe }}

    {% endfor %}


text:
package guard

import (
	"time"

	"gopkg.in/workanator/go-floc.v2"
)

// Deadline protects the job from doing the job after the deadline. The job
// is run in it's own goroutine while the current goroutine waits until
// the job finished or the deadline came or the flow is finished.
func Deadline(when WhenDeadlineFunc, id interface{}, job floc.Job) floc.Job {
	return OnDeadline(when, id, job, nil)
}

// OnDeadline protects the job from doing the job after deadline.
// In addition it takes TimeoutTrigger func which called if time is out.
// The job is run in it's own goroutine while the current goroutine waits
// until the job finished or the deadline came or the flow is finished.
func OnDeadline(when WhenDeadlineFunc, id interface{}, job floc.Job, timeoutTrigger TimeoutTrigger) floc.Job {
	// Construct the job with Timeout guard.
	whenTimeout := func(ctx floc.Context, id interface{}) time.Duration {
		return time.Until(when(ctx, id))
	}

	return OnTimeout(whenTimeout, id, job, timeoutTrigger)
}


text:
<?php

/**
 * Please note this file shouldn't be exposed on a live server,
 * there is no filtering of $_POST!!!!
 */

//--------------------------------------------------------------------
// User Configurable Options
//--------------------------------------------------------------------

// System Folder Paths
//
// Customize these paths if you are using a folder layout other than
// what is provided by default with Bonfire.
$folder = realpath(dirname(__FILE__)).'/';
define('MAIN_PATH', str_replace('tests/', '', $folder));
define('SIMPLETEST', MAIN_PATH .'tests/simpletest/');	// Directory of simpletest
define('ROOT', MAIN_PATH .'public/'); 					// Directory of codeigniter index.php
define('TESTS_DIR', MAIN_PATH . 'tests/'); 				// Directory of your tests.
define('APP_DIR', MAIN_PATH . 'application/'); 			// CodeIgniter Application directory
define('BF_DIR', MAIN_PATH .'bonfire/');				// Bonfire core directory

// Ignore Folders
//
// This array contains names of folders, relative to the
// base 'tests' folder that will be ignored when doing a scan
// the folders to locate tests.
//
//  This can be modified at runtime with to include/exclude app-specific
//  or Bonfire core folders with the --app_only or -bf_only options on the CLI
$ignore_folders = array(
	TESTS_DIR .'support',
	TESTS_DIR .'simpletest'
);

// Only Folder
//
// Will only have a value if the -d or --dir flags were used on the CLI
$only_folder = NULL;

// Only File
//
// Will only have a value if the -f or --file flags were used on the CLI
$only_file = isset($_POST['test']) && !empty($_POST['test']) ? $_POST['test'] : null;

//--------------------------------------------------------------------
// END User Configurable Values
//--------------------------------------------------------------------
// Do not edit below this line unless you know what you are doing.
//

//do not use autorun as it output ugly report upon no test run
require_once SIMPLETEST . 'unit_tester.php';
require_once SIMPLETEST . 'mock_objects.php';
require_once SIMPLETEST . 'collector.php';
require_once SIMPLETEST . 'web_tester.php';
require_once TESTS_DIR . '_support/my_reporter.php';

// Bypass any CSRF protection in order to avoid
// modifying simpletest
//
if (isset($_SERVER["REQUEST_METHOD"]) && $_SERVER["REQUEST_METHOD"] == "POST" && isset($_COOKIE['ci_csrf_token']))
{
	$_POST['ci_csrf_token'] = $_COOKIE['ci_csrf_token'];
}

//Capture CodeIgniter output, discard and load system into $ci variable
ob_start();
	include(ROOT . 'index.php');
	$ci =& get_instance();
ob_end_clean();

//--------------------------------------------------------------------
// TEST CLASSES
//--------------------------------------------------------------------
// These classes provide CodeIgniter & Bonfire-specific setup needed
// to use SimpleTest with the project.
//

/**
 * CI_UnitTestCase
 *
 * Provides an parent class our tests can run from. This class extends
 * from the default SimpleTest UnitTestCase file. It provides access
 * to the $this object in a CI-style manner, as well as additional
 * assertions:
 *
 * 		- assertEmpty()
 * 		- assertNotEmpty()
 */
class CI_UnitTestCase extends UnitTestCase {

	protected $ci;

	//--------------------------------------------------------------------

	public function __construct()
	{
		parent::__construct();
		$this->ci =& get_instance();
	}

	//--------------------------------------------------------------------

	/**
	 * Allows us to transparently use CI-standard $this->load, etc.
	 * in our tests and still have them function correctly in the
	 * test files.
	 *
	 * @return  mixed
	 *
	 * @access  public
	 */
	public function __get($var)
	{
		return $this->ci->$var;
	}

	//--------------------------------------------------------------------

	/**
	 * Will be true if the value is empty.
	 *
	 * @param  mixed  $value   Supposedly empty value.
	 * @param  string $message Message to display.
	 *
	 * @return boolean True on pass.
	 *
	 * @access public
	 */
	public function assertEmpty($value, $message = '%s')
	{
		$dumper = new SimpleDumper();
		$message = sprintf($message, '[' . $dumper->describeValue($value) . '] should be empty');
		return $this->assertTrue(empty($value), $message);

	}

	//--------------------------------------------------------------------

	/**
	 * Will be true if the value is not empty.
	 *
	 * @param  mixed  $value   Supposedly not empty value.
	 * @param  string $message Message to display.
	 *
	 * @return boolean True on pass.
	 *
	 * @access public
	 */
	public function assertNotEmpty($value, $message = '%s')
	{
		$dumper = new SimpleDumper();
		$message = sprintf($message, '[' . $dumper->describeValue($value) . '] should not be empty');
		return $this->assertFalse(empty($value), $message);

	}

	//--------------------------------------------------------------------
}	// end CI_UnitTestCase

//--------------------------------------------------------------------

/**
 * CI_WebTestCase
 *
 * Inherits from the SimpleTest WebTestCase class to provide a simple
 * means of accessing the CI $this object when running tests against the
 * Web pages themselves.
 */
class CI_WebTestCase extends WebTestCase {

	protected $ci;

	//--------------------------------------------------------------------

	public function __construct()
	{
		parent::WebTestCase();
		$this->ci =& get_instance();
	}

	//--------------------------------------------------------------------

	public function __get($var)
	{
		return $this->ci->$var;
	}

	//--------------------------------------------------------------------
}	// end CI_WebTestCase

//--------------------------------------------------------------------
// END TEST CLASSES
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// UTILITY FUNCTIONS
//--------------------------------------------------------------------

/**
 * Function to determine if in cli mode and if so set up variables to make it work
 *
 * @param Array of commandline args
 * @return Boolean true or false if commandline mode setup
 *
 */
function setup_cli($argv)
{
	if (php_sapi_name() == 'cli')
	{
		if(isset($argv[1]))
		{
			if(stripos($argv[1],'.php') !== false)
			{
				$_POST['test'] = $argv[1];
			}
			else
			{
				$_POST[$argv[1]] = $argv[1];
			}
		}
		else
		{
			$_POST['all'] = 'all';
		}
		$_SERVER['HTTP_HOST'] = '';
		$_SERVER['REQUEST_URI'] = '';
		return true;
	}
	return false;
}

//--------------------------------------------------------------------

/**
 * Function to map tests and strip .html files.
 *
 * @param	string
 * @return 	array
 */
function map_tests($location = '')
{
	if (empty($location))
	{
		return FALSE;
	}

	$files = directory_map($location);
	$return = array();

	foreach ($files as $file)
	{
		if ($file != 'index.html')
		{
			$return[] = $file;
		}
	}
	return $return;
}

//--------------------------------------------------------------------

/**
 * A simple copy of CI's memory_usage method that we use to
 * provide a quick overview of memory usage. This is mainly to ensure that
 * none of the scripts are getting out of hand.
 *
 * @return strign The amount of memory used
 */
function memory_usage()
{
	$size = memory_get_usage(true);

	$unit=array('B','KB','MB','GB','TB','PB');
	return @round($size/pow(1024,($i=floor(log($size,1024)))),2).' '.$unit[$i];
}

//--------------------------------------------------------------------

/**
 * discover_tests
 *
 * Given a base folder, it will recursively scan a folder to
 * determine which files are valid test files. Valid test files
 * must have either 'Test' or '_test' in their name.
 *
 * @param  string $start_folder The folder to start scanning. If empty, it will
 *                              	be the base of the tests folder.
 * @param boolean $ignore_onlys If TRUE, will ignore checks for $only_file and $only_folder
 *                              Primarily used for recursive scans.
 * @return array               The list of test files.
 */
function discover_tests($start_folder=null, $ignore_onlys=false)
{
	global $ignore_folders, $only_file, $only_folder;
	$files = array();

	// If no start folder exists, we'll
	// set it manually to our tests root
	if (is_null($start_folder))
	{
		$start_folder = TESTS_DIR;
	}

	// If this is one of the ignore folders
	// simply return an empty array.
	if (in_array($start_folder, $ignore_folders))
	{
		return array();
	}

	$start_folder = rtrim($start_folder, '/');

	// Are we restricting to a single file?
	if ($only_file && !$ignore_onlys)
	{
		if (is_file($start_folder .'/'. $only_file))
		{
			$files[] = $start_folder .'/'. $only_file;
			return $files;
		}
	}

	if (!function_exists('directory_map'))
	{
		global $ci;
		$ci->load->helper('directory');
	}

	$folders = directory_map($start_folder, 1);

	// Look through all of our folders & files for
	// valid test files.
	if (is_array($folders))
	{
		foreach ($folders as $folder)
		{
            // remove trailing backslash
            $folder = rtrim($folder, DIRECTORY_SEPARATOR);

			// Folders get ran back through this function
			// and will return an array of valid files.
			// Merge this array with ours and call it good.
			if (is_dir($start_folder .'/'. $folder) && !in_array($start_folder .'/'. $folder, $ignore_folders))
			{
				$f = discover_tests($start_folder .'/'. $folder, true);
				$files = array_merge($files, $f);
			}
			else if (is_file($start_folder .'/'. $folder))
			{
				// Does it appear to be a valid filename?
				if (strpos($folder, 'Test')  OR strpos($folder, '_test'))
				{
					$files[] = $start_folder .'/'. $folder;
				}
			}
		}
	}

	return $files;
}

//--------------------------------------------------------------------
// END UTILITY FUNCTIONS
//--------------------------------------------------------------------

// Make sure we have plenty of time to run the tests.
error_reporting(E_ALL ^ E_NOTICE);

// Are we running in cli mode?
$is_cli = setup_cli($argv);

if ($is_cli)
{
	// Setup our allowed short/long options
	$short_opts  = '';
	$short_opts .= 'a';			// Include the applications folder tests only. Not Bonfire core.
	$short_opts .= 'b';			// Include Bonfire's core tests only, not the app-specific ones.
	$short_opts .= 'f:';		// Restrict to a single file
	$short_opts .= 'd:';		// Restrict to a single folder

	$long_opts  = array(
		'app_only',				// Include the applications folder tests only. Not Bonfire core.
		'bf_only',				// Include Bonfire's core tests only, not the app-specific ones.
		'file:',				// Restrict to a single file
		'dir:',					// Restrict to a single folder
	);

	$cli_opts = getopt($short_opts, $long_opts);

	// If we are on an app_only or bf_only run,
	// then add the folders to the ignored folders
	if (array_key_exists('a', $cli_opts) || array_key_exists('app_only', $cli_opts))
	{
		$ignore_folders[] = str_replace('src', 'tests', BF_DIR);
	}
	else if (array_key_exists('b', $cli_opts) || array_key_exists('bf_only', $cli_opts))
	{
		$ignore_folders[] = str_replace('src', 'tests', APP_DIR);
	}
	else if (array_key_exists('f', $cli_opts) || array_key_exists('file', $cli_opts) )
	{
		$only_file = array_key_exists('file', $cli_opts) ? $cli_opts['file'] : $cli_opts['f'];
	}
	else if (array_key_exists('d', $cli_opts) || array_key_exists('dir', $cli_opts) )
	{
		$only_folder = array_key_exists('dir', $cli_opts) ? $cli_opts['dir'] : $cli_opts['d'];
	}
}

// Setup similar options via $_GET vars for the GUI version
else
{
	if (isset($_GET['a']) || isset($_GET['app_only']) || isset($_POST['app_only']))
	{
		$ignore_folders[] = rtrim( str_replace('src', 'tests', BF_DIR), '/');
	}
	else if (isset($_GET['b']) || isset($_GET['bf_only']) || isset($_POST['bf_only']))
	{
		$ignore_folders[] = rtrim(str_replace('src', 'tests', APP_DIR), '/');
	}
	else if (isset($_GET['f']) || isset($_GET['file']))
	{
		$only_file = isset($_GET['f']) ? $_GET['f'] : $_GET['file'];
	}
	else if (isset($_GET['d']) || isset($_GET['dir']))
	{
		$only_folder = isset($_GET['d']) ? $_GET['d'] : $_GET['dir'];
	}
}

$test_suite = new TestSuite();
$test_suite->_label = 'Bonfire Test Suite';

// We destroy the session here so that tests can create
// their own sessions. This also allows us to not contaminate test
// results with our own session information.
$ci->load->library('session');
$ci->session->sess_destroy();

$ci->load->helper('directory');

// Start your engines!
$test_start = microtime();

$test_files = null;

// TODO Revise to allow args from the CLI as folder/file names
$only_folder = isset($only_folder) && !empty($only_folder) ? TESTS_DIR . $only_folder : null;

$all_tests = discover_tests(TESTS_DIR, true);

$test_files = discover_tests($only_folder);

// Add the found test files to the suite to be tested.
if (is_array($test_files))
{
	foreach ($test_files as $file)
	{
		$test_suite->addFile($file);
	}
}

// ------------------------------------------------------------------------

//variables for report
/*
$controllers = map_tests(TESTS_DIR . 'controllers');
$models = map_tests(TESTS_DIR . 'models');
$views = map_tests(TESTS_DIR . 'views');
$libraries = map_tests(TESTS_DIR . 'libraries');
$bugs = map_tests(TESTS_DIR . 'bugs');
$helpers = map_tests(TESTS_DIR . 'helpers');
*/
$form_url =  'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

$test_end = microtime();

/* Benchmark */
list($sm, $ss) = explode(' ', $test_start);
list($em, $es) = explode(' ', $test_end);

$elapse_time =  number_format(($em + $es) - ($sm + $ss), 4);

//display the form
if ($is_cli) {
	exit ($test_suite->run(new TextReporter()) ? 0 : 1);
}
else {
	include(TESTS_DIR . 'test_gui.php');
}


text:
package javax.enterprise.inject.spi;

public interface Prioritized {

   /**
    *
    * @return the priority of this component
    */
   int getPriority();
}