#!/usr/bin/perl

use 5.034;

my $DEBUG = 0;

my $planta = <<EOT;
OIOOIOOIOOIO
OIOOIOOIOOIO
OIOOIOOIOOIO
OIOOIOOIOOIO
OIOOIOOIOOIO
OIII&IIIIIIO
EOT
;
$planta =~ s/\s//g;
$planta = $planta x 3;   # son tres plantas
my $P = 3;
my $F = 6;
my $C = 12;
my @caisles = (2, 5, 8, 11); 

my @array;
my @index;
my @w = split "", $planta;
my $pos="0-6-5"; # nivel 0 esperando fila 5 columna 4

my $kontador;
my @rindex;
for my $p (1 .. $P){
    for my $fila (1..$F){
	for my $c (1 .. $C){
	    my $k = shift @w;
	    $array[$p][$fila][$c]= $k;
	    say "$p $fila $c -> $k" if $DEBUG;
	    $index[++$kontador] = "$p-$fila-$c";
	    say "index $kontador = $p-$fila-$c" if $DEBUG;
	}
    }	
}
my %rindex = reverse @index;

my $alturas = $P;
my $velocidad = 0.3; # metros/segundo
my $tiempometer = 10; # segundos
my $ascensorcongiro = 30; # segundos
my $retirada = 12; # segundos
my $largoplaza = 5; # metros 
my $altoplaza = 2; # metros
my $anchoplaza = 2.5; # metros

say "Dimensiones:";
say "Ancho = ", $anchoplaza*$C, " metros";
say "Largo = ", $largoplaza*$F, " metros";
say "Alto = ", $altoplaza*$P, " metros";  

my ($capacidad, $pasillo, $elevador);
# my @posx;
my $cola;

for my $i (split (//, $planta)) {
    if ($i eq "O") {
	$capacidad++;
#	$posx[$capacidad-1] = $index[$kontador--] if (($index[$kontador] ne $index[$kontador+1]));
    }elsif ($i eq "&"){
	$elevador++;
    }else{
	$pasillo++;
    }
}

say "";
say "capacidad (5x8+2)x3 = $capacidad";
say "pasillo ((4x6)+6)x3 = $pasillo"; 
say "elevador 1x3+1 (planta 0) = $elevador+1";
say "";
my ($llegada, $peticion, $insercion);

my $t =0;
my ($id, $lleno);
my ($x,$y,$z);
my @lista;
push @lista, rand()*48-24 for 1..100_000;
@lista = sort { $a <=> $b } @lista;
my $c;
while (@lista){    
    $llegada = shift (@lista); #   rand()*48-24;
    if ($llegada <=0){                                   # RETIRADA
	$x = int rand()*($P+1);
	$y = int rand()*(1+$F);
	$z = int rand()*(1+$C);
	$peticion = "$x-$y-$z";
	$insercion = 0;
	$t += mov ( $pos , $rindex{$peticion} );
	$t += $retirada;
	$t += mov ( $rindex{$peticion}, "0-6-5" );
	$t += $ascensorcongiro;
	$array[$x][$y][$z] = "O" if $array[$x][$y][$z] > 0;
    }else{                                               # INSERCION
	$id = 1+int (123456789 * rand()); 
	$insercion = algoritmo($pos);
	if ($insercion eq "FULL"){
	    $lleno++;
	    next;
	}
	$peticion = 0;
	$t += $ascensorcongiro;
	$t += mov ( $insercion , "0-6-5" );
	$t += $tiempometer;
	$t += mov ( "0-6-5", $insercion );
    }
    print "\rTiempo medio = " , int($t / ++$c), " segundos";
}

say "";
say "Fracasos por llenos ", $lleno/100_000;
say "";
exit 2;


sub mov {
    my ($x, $y) = @_;
    $x =~ /(\d+)\-(\d+)-(\d+)/;
    my $piso = $1;
    my $fila = $2;
    my $col = $3;

    
    $y =~ /(\d+)\-(\d+)\-(\d+)/;
    my $pison = $1;
    my $filan = $2;
    my $coln = $3;

    my ($dist, $dp, $df, $dc);
    
    $dp = abs ($pison - $piso);
    $df = abs ($filan - $fila);
    
    if (abs($coln - $col) <= 1){
	$dc = 0;
    }elsif (abs($coln - $col) > 1){
	$df *= 2;
	$dc = abs ($coln -$col);
    }
#    $dist = $dp + $df + $dc;
    my $tt = 0;
    $tt = $dp * $altoplaza / $velocidad + $df * $anchoplaza / $velocidad + $dc * $largoplaza / $velocidad;
    $pos = $y;
    return $tt;
}

sub algoritmo {     # algoritmo de inserción a lo más cercano
    my $pos = shift;
#    my $t = mov ( $pos, "0-6-5" );
    my ($x, $y, $z, $r, $c);
    do {
	$c++;
	$x = int rand()*($P+1);
	$y = int rand()*($F+1);
	$z = int rand()*($C+1);
#	$r = mov ( "0-6-5", "$x-$y-$z" );	
    }until ($array[$x][$y][$z] eq "O" || $c>=100);
    if ($c >= 100){
	for $y (1..$F){
	    for $z (1..$C){
		for $x (1..$P){
		    goto ya if ($array[$x][$y][$z] eq "O");
		}
	    }
	}
	if ($y == $F) { 
	    $pos = "0-6-5";
	    return "FULL"; 
	}
    }
ya:    
    $array[$x][$y][$z] = $id;
#   $t += $r;
    $pos = "$x-$y-$z";
    return $pos;
}


__END__
  
It suggest a second lift is needed
  
