#!/usr/bin/perl -w

%formato=(numero=>7,    # Tamanho da coluna de números.
          operacao=>8,  # Tamanho da coluna de operações.
          ced=>6,       # Espaço entre a coluna de créditos e a de débitos.
          maxnum=>15,   # Máximo de dígitos que o programa suporta. Também define o tamanho das colunas de números.
          S=>"Saldo", D=>"Depósito", C=>"Cheque", Q=>"Saque");
%banco=(Ss=>0,Sn=>0,Ds=>0,Dn=>0,Cs=>0,Cn=>0,Qs=>0,Qn=>0); # Guarda diferentes valores totais.
#open (DADOS,"saida");
foreach(<>){
  next unless /^\s*([SDCQ])\s+(\d{1,$formato{maxnum}}),(\d\d)\s+(\d\d)\/(\d\d)\/(\d{4})\s+([\*(?:\d+)])\s+([sn])\s*$/;
   # É fácil ver que a expressão regular acima combina com padões que: comecem ou não com espaços; tenham uma definição de operação (S, D, C ou Q); espaço(s); um valor, de no máximo 10^12 reais e 99 centavos (se alguém tiver mais do que isso em sua conta bancária, pode me pagar uns trocados para mudar uma linha no programa), sem indicador de moeda e devendo sempre ter os centavos, onde o separador de casas decimais é a vírgula (e não o ponto, uma vez que estamos no Brasil); espaço(s); uma data no formato dd/mm/aaaa; espaco(s); um número ou asterisco; espaço(s); e finalmente s ou n; podendo ter espaços até o fim da linha. Esse é o único formato que a entrada pode ter, qualquer coisa diferente disso será ignorada como se fosse comentário.
   # $1:Operação, $2:Parte inteira do valor, $3:Centavos, $4:Dia, $5:Mes, $6:Ano, $7:Numero, $8:Pendencia.

   if ($1 eq "S") {next if $S; $S++;} # Só a primeira declaração de saldo é considerada.
   $chave="$1"."$8";
   $num=$7;
   $num="0"x($formato{"numero"}- (length $num))."$num"; # Colocando o espaçamento certo no número.
   $data="$6"."$5"."$4"."$num"; # Data na forma aaaammdd, concatenada com o numero, para ordenar facilmente e sem problemas.
   $valor=$2*100+$3; # Juntando os pedaços do valor.
   $banco{$chave}+=$valor; # Soma todos os valores na variável adequada, que será manipulada mais tarde.
   $saida{$data}=["$valor","$1","$8"]; # ($saida{$data})->[0] é $valor, [1] é $1, [2] é $8.
}

$Saldo=$banco{Ss}+$banco{Sn};         # A pendência é irrelevante para o saldo, saque e depósito.
$CR=$CP=$banco{Ds}+$banco{Dn};        # Sim, o crédito real é sempre igual ao previsto. e eles só dependem dos depósitos.
$DR=$banco{Qs}+$banco{Qn}+$banco{Cn}; # O débito real depende dos saques e dos cheques não pendentes,
$DP=$DR+$banco{Cs};                   # o previsto depende também dos cheques pendentes.
$TR=$CR+$DR;                          # O total de dinheiro movimentado pode ser útil para calcular o CPMF, por exemplo.
$TP=$CP+$DP;                          # E tem dois valores possíveis, já que depende do débito.
$VP=$CP-$DP;                          # Variação prevista do saldo (ou Delta Saldo)).
$VR=$CR-$DR;                          # Surpresa desagradável.
$FR=$Saldo+$VR;                       # 'F' de saldo Final (ou julgamento Final).
$FP=$Saldo+$VP;                       # Representação financeira de "menos infinito".

print "-"x(60+2*$formato{"maxnum"}+$formato{"ced"}); print "\n";
$c=" "x($formato{"maxnum"}-(length $Saldo)-1); # Espaçamento certo e colocação
$Saldo=~s/(.*)(\d\d)/$c$1,$2/;                 # da vírgula no saldo.
print "SALDO INICIAL:"." "x8; print "$Saldo\n\n";
print "   DATA"." "x($formato{"maxnum"}+8);
print "CRÉDITO"." "x($formato{"ced"}+$formato{"maxnum"}-6);
print "DÉBITO"." "x6;
print "OPERAÇÃO"." "x4; print "NÚMERO"." "x5; print "PENDÊNCIA\n";

foreach $d (sort keys %saida){
   next if ($saida{$d})->[1]=~/^S/; # O saldo já foi.
  
   $operacao=(($saida{$d})->[1]);
   $operacao=$formato{$operacao};
   $c=" "x($formato{"operacao"}- (length $operacao));    # Quatro linhas para colocar o 
   $operacao=~s/(.*)/$1$c/;                            # espaçamento certo na operação.

   # O bloco seguinte é um pouco mais complicado. Aqui os depósitos (que são as únicas formas de crédito, além do saldo inicial) são colocados na mesma coluna que os débitos (infelizmente de vários tipos). Mas, para parecer que são duas colunas distintas, os depósitos são jogados para a esquerda. Depois, tudo recebe o espaçamento configurado para a megaculona de créditos e débitos. No final do bloco, tanto os débitos quanto os créditos ganham as suas devidas vírgulas, para não deixar o usuário cem vezes mais rico de repenteaida{$d})->[0]);
   $valor=(($saida{$d})->[0]);
   if ($operacao eq "Depósito"){
      $c=" "x($formato{"ced"}+$formato{"maxnum"});
      $valor=~s/(.*)/$1$c/;
   }
   $c=" "x($formato{"ced"}+2*$formato{"maxnum"}- (length $valor) -1);
   $valor=~s/(.*)(\d\d)/$c$1,$2/;

   $pendencia=(($saida{$d})->[2]);
   $d=~s/^(\d\d\d\d)(\d\d)(\d\d)(\d{$formato{"numero"}})$/$3\/$2\/$1/; # Colocando a data na forma certa.
   $numero=$4;

   print "$d"." "x12; print "$valor"; print " "x6; print "$operacao"." "x4; print "$numero"." "x9; print "$pendencia\n";
}

foreach $var ($CR,$CP,$DR,$DP,$TR,$TP,$VR,$VP,$FR,$FP){
   $c=" "x($formato{"maxnum"}-(length $var) -1);
   $var=~s/(.*)(\d\d)/$c$1,$2/;
}

print "\nTOTAL REAL:"." "x11; print "$CR"." "x$formato{"ced"}."$DR\n";
print "TOTAL PREVISTO:"." "x7; print "$CP"." "x$formato{"ced"}."$DP\n\n";
print " "x(22+$formato{"maxnum"}-4); print "REAL"." "x($formato{"maxnum"}+$formato{"ced"}-8)."PREVISTO\n";
print "TOTAL MOVIMENTADO:"." "x4; print "$TR"." "x$formato{"ced"}."$TP"." "x28; print "Criado por\n";
print "VARIAÇÃO DE SALDO:"." "x4; print "$VR"." "x$formato{"ced"}."$VP"." "x12; print "Vitor Eiji Justus Sakaguti\n";
print "SALDO FINAL:"." "x10; print "$FR"." "x$formato{"ced"}."$FP"." "x25; print "em 03/07/2005\n";
print "-"x(60+2*$formato{"maxnum"}+$formato{"ced"}); print "\n";
