program cappali(input,output);
const
  lnome=30;
  lcol=78;
  nummax=797;
  maxper=30;
  r=0.142;
type
 recdati=record
           imax:real;
           imin:real;
           k:real;
           k2:real;
           a:real;
           a2:real
           end;
 vettdatimis=array[1..nummax]of real;
 vettdatical=array[1..maxper]of recdati;
 vettcom=array[1..lcol]of char;
 vettnome=array[1..lnome]of char;
var
  datimis:vettdatimis;
  datical:vettdatical;
  commento:vettcom;
  nome:vettnome;
  infile,outfile,grafile:text;
  col,ind,numper,nummis,soglia,numdati,caso:integer;
  kmedio,amedio,amedia_k,dev,divper,lenght:real;
  kmedio2,amedio2,amedia_k2,dev2,divper2:real;
  flg:boolean;
procedure legginomefile(var nfile:vettnome;scelta:integer);
  begin
  case scelta of
    1:write('nome del file da caricare:');
    2:write('nome del file di uscita:');
    3:write('nome del file per la grafica:');
    end;
    for ind:=1 to lnome do nfile[ind]:=' ';
    ind:=0;
    while not eoln and (ind<lnome) do
      begin
        ind:=ind+1;
        read(nfile[ind]);
      end;
 readln;
end;
procedure leggifile(var filin:text;var com:vettcom;var dati:vettdatimis;
                      var conta,numerodati:integer);
begin
  reset(filin);
  for col:=1 to lcol do com[col]:=' ';
  col:=0;
  while not eoln(filin) do
     begin
       col:=col+1;
       read(filin,com[col]);
     end;
  readln(filin);
  readln(filin,numerodati);
  conta:=0;
  while not eof(filin) do
      begin
        conta:=conta+1;
        readln(filin,dati[conta]);
      end;
  close(filin);
end;
procedure calcoladatiuscita(var dati:vettdatimis;var fl:boolean;
                            nmis,thresold:integer;var nper:integer;
                            var km,km2,am,am2,a_k,a_k2,deviaz,
                            deviaz2:real);
   var
     contatore:integer;
  procedure cercamaxmin(var dat:vettdatimis;var conta,per:integer;
                        var cal:vettdatical;th,nm:integer);
        var
          maxsto,maxnew:real;distanza,min_maxnew:integer;
      begin
       maxsto:=0.0;distanza:=0;
       while(distanza<th)and(conta<nm) do
         begin
           while(dati[conta]<dati[conta+1])or (dati[conta]=dati[conta+1])do
           conta:=conta+1;
           maxnew:=dati[conta];
           if maxnew>maxsto then maxsto:=maxnew;
           min_maxnew:=0;
           while(dati[conta]>dati[conta+1])or(dati[conta]=dati[conta+1]) do
             begin
             conta:=conta+1;
             min_maxnew:=min_maxnew+1;
             end;
           distanza:=min_maxnew;
         end;
       if conta<nm then
              begin
               per:=per+1;
               cal[per].imax:=maxsto;
               cal[per].imin:=dati[conta];
             end;
  end;
 procedure cercaminmax(var dat:vettdatimis;var conta,per:integer;
                       var cal:vettdatical;th,nm:integer);
  var
     minsto,minnew:real;
     distanza,max_minnew:integer;
   begin
      distanza:=0;
      minsto:=10.0;
      while(distanza<th)and(conta<nm) do
         begin
          while(dati[conta]>dati[conta+1])or(dati[conta]=dati[conta+1])do
          conta:=conta+1;
          minnew:=dati[conta];
          if minnew<minsto then minsto:=minnew;
          max_minnew:=0;
          while(dati[conta]<dati[conta+1])or(dati[conta]=dati[conta+1])do
              begin
                conta:=conta+1;
                max_minnew:=max_minnew+1;
              end;
          distanza:=max_minnew;
          end;
       if conta<nm then
       begin
         per:=per+1;
         cal[per].imax:=dati[conta];
         cal[per].imin:=minsto;
        end;
end;
procedure calcolacappaalfa(per:integer;var cal:vettdatical;l:real);
 var
   num,den:real;
   begin
   num:=cal[per].imax-cal[per].imin;
   den:=cal[per].imax+cal[per].imin;
   if ((num/den<=0)or(num/den>=1))
   then per:=per-1
   else
         begin
           cal[per].k:=num/den;
           cal[per].a:=4.34/l*(ln(r)+ln(2)-ln(cal[per].k));
         end;
   end;
procedure statistica(per:integer; var cal:vettdatical;var flag:boolean;
                     var k,k2,a,a2,ak,ak2,dp,dp2:real;l:real);
   var
   sommak,sommaa,sommak2,sommaa2:real;
   quad,quad2,deviazione,deviazione2:real;
   num,den:real;
   begin
     for ind:=1 to(per-1) do
     begin
     num:=(((cal[ind].imax+cal[ind+1].imax)/2)-cal[ind].imin);
     den:=(((cal[ind].imax+cal[ind+1].imax)/2)+cal[ind].imin);
     cal[ind].k2:=num/den;
     end;
   num:=(cal[per-1].imax-((cal[per-2].imin+cal[per-1].imin)/2));
   den:=(cal[per-1].imax+((cal[per-2].imin+cal[per-1].imin)/2));
   cal[per].k2:=num/den;
   ind:=0;
   flag:=false;
   while (ind<per) and not flag do
    begin
    ind:=ind+1;
    if(cal[ind].k2<=0)or(cal[ind].k2>=1) then
     begin
     for ind:=1 to per do cal[ind].k2:=cal[ind].k;
     flag:=true;
     end;
   end;
   for ind:=1 to per do cal[ind].a2:=(4.34/l)*(ln(r)+ln(2)-ln(cal[ind].k2));
   sommak:=0;
   sommaa:=0;
   sommak2:=0;
   sommaa2:=0;
   for ind:=1 to per do
    begin
     sommak:=sommak+cal[ind].k;
     sommaa:=sommaa+cal[ind].a;
     sommak2:=sommak2+cal[ind].k2;
     sommaa2:=sommaa2+cal[ind].a2;
     end;
     k:=sommak/per;
     a:=sommaa/per;
     k2:=sommak2/per;
     a2:=sommaa2/per;
     quad:=0;
     quad2:=0;
     for ind:=1 to per do quad:=quad+sqr(a-cal[ind].a);
     for ind:=1 to per do quad2:=quad2+sqr(a2-cal[ind].a2);
     deviazione:=sqrt(quad/per);
     deviazione2:=sqrt(quad2/per);
     dp:=deviazione/a;
     dp2:=deviazione2/a2;
     ak:=(ln(r)+ln(2)-ln(k))*4.34/l;
     ak2:=(ln(r)+ln(2)-ln(k2))*4.34/l;
     end;
      begin
       contatore:=1;
       nper:=0;
       while dati[contatore]=dati[contatore+1] do contatore:=contatore+1;
       if dati[contatore]<dati[contatore+1] then
          begin
       while contatore<nmis do
       begin
       cercamaxmin (dati,contatore,nper,datical,thresold,nmis);
       calcolacappaalfa(nper,datical,lenght);
       end;
      end;
      else begin
      cercaminmax(dati,contatore,nper,datical,thresold,nmis);
      calcolacappaalfa(nper,datical,lenght);
      end;
     end;
     statistica(nper,datical,fl,km,km2,am,am2,a_k,a_k2,deviaz,deviaz2,lenght);
     end;
begin
write('valoarea distantei dintre un max si un min consecutiv:');
readln(soglia);
write('lungimea ghidului in cm:');
readln(lenght);
caso:=1;
legginomefile(nome,caso);
assign(infile,nome);
leggifile(infile,commeto,datimis,nummis,numdati);
calcoladatiuscita(datimis,flg,nummis,soglia,numper,kmedio,kmedio2,amedio,
                  amedio2,amedia_k,amedia_k2);
caso:=caso+1;
legginomefile(nome,caso);
assign(outfile,nome);
rewrite(outfile);
writeln(outfile,nome);
for col:=1 to lcol do write(outfile,commento[col]);
writeln(outfile);
writeln(outfile,numdati);
writeln(outfile,'numere periodice: ',numper);
writeln(outfile);
for ind:=1 to numper do
 writeln(outfile,'imax[',ind,']=',datical[ind].imax:18,'imin[',ind,']=',
           datical[ind].imin:18);
 writeln(outfile);
 for ind:=1 to numper do
   writeln(outfile,'k[ ',ind,' ]=',datical[ind].k:18,' a[ ',ind,' ]=',
            datical[ind].a:18);
writeln(outfile);
writeln(outfile,'valoarea contrastului mediu k:',kmedio);
writeln(outfile,'valoarea atenuarii medii:',amedio,'db/cm');
writeln(outfile,'valoarea atenuarii,functie de k mediu:',amedia_k,'db/cm');
writeln(outfile,'valoarea deviatiei in procente:',dev);
writeln(outfile);
if flg then writeln(outfile,'n.b.i valorile lui k au fost calculate
                     cu formula lui k ...');
       else writeln(outfile,'valori obtinute prin calcul alternativ
                         al lui k');   writln(outfile);
for ind:=1 to numper do
writeln(outfile,'k[ ',ind,']=',datical[ind].k2:18,'a[',ind,']=',
                    datical[ind].a2:18,'db/cm');
writeln(outfile);
writeln(outfile,'valoarea contrastului mediu k:',kmedio2);
writeln(outfile,'valoarea atenuarii medii:',amedio2,'db/cm');
writeln(outfile,'valoarea atenuarii functie de k mediu:',amedia_k2,'db/cm');
writeln(outfile,'valoarea procentuala a deviatiei:',dev2);
close(outfile);
caso:=caso+1;
legginomefile(nome,caso);
assign(grafile,nome);
rewrite(grafile);
for ind:=1 to numper do
writeln(grafile,datical[ind].k2:18,datical[ind].a2:20);
close(grafile);
end.
end.