﻿//KyblKdeJsem v1.6
//www.kyblsoft.cz/mobil/

use array,bigint,gsm,io,math,time

soubor='D:\\seznambts.dat';
maxminutnanezobrazeni=10*60;
maxpolozeknanezobrazeni=3;
minminutvcache=60;
zapisovatposlednibts=false;

.aktualnicas=null;

function cmp(pole1,pole2)
  for i=0 to len(pole1)-1 do
    if pole1[i] # pole2[i] then
      if pole1[i] < pole2[i] then
        return -1;
      else
        return 1;
      end;
    end;
  end;
  return 0;
end;

function Cti8bitCislo(f,nakolik)
  navrat=0;
  cisla=code(io.read(f,nakolik));

  for i=0 to nakolik-1 do
    navrat = navrat*256;
    navrat += cisla[i];
  end;

  return navrat;
end;

function Vrat8BitPole(cislo,delka)
  vysledek=[];
  while delka > 0 do
    array.insert(vysledek,0,bigint.num(bigint.mod(cislo,256)));
       //bug mShellu 3
    cislo=math.floor(cislo/256);
    delka--;
  end;

  if cislo # 0 then throw null; end;

  return vysledek;
end;

function VratLokaci(cid,lac)
  f=io.open(.soubor,false,io.raw);
  verze=Cti8bitCislo(f,1);
  if verze # 1 then
    print 'Nesprávná verze datového souboru!';
    return null;
  end;
  pocetbts=Cti8bitCislo(f,2);

  hledatpole=Vrat8BitPole(cid*65536+lac,4);

  posun=3;
  delkabunky=2+2+3;

  levy=0; pravy=pocetbts-1;

  while levy <= pravy do
    pozice=math.floor((levy+pravy)/2);
    io.seek(f,posun+pozice*delkabunky);
    data=code(io.read(f,2+2));
    case cmp(data,hledatpole)
      in 0:
        pozice=posun+pocetbts*delkabunky+Cti8bitCislo(f,3);
        io.seek(f,pozice);
        delka=Cti8bitCislo(f,1);
        io.ces(f,io.utf8);
        okres=io.read(f,2);
        popis=trim(io.read(f,delka-2));
        return ['cislopopisu': pozice,'okres': okres,'popis': popis];
      in 1:
        pravy=pozice-1;
      in -1:
        levy=pozice+1;
    end;
  end;

  io.close(f);

  return ['cislopopisu': cid*65536+lac+pocetbts,'okres': '?','popis': 'LAC '+lac+', CID '+cid];
end;

function VratZCache(idbts,predchozibtsky,bts)
  for i=len(predchozibtsky)-1 to 0 by -1 do
    for i2=len(predchozibtsky[i]['idbts'])-1 to 0 by -1 do
      if idbts = predchozibtsky[i]['idbts'][i2] then
        bts['popis']=predchozibtsky[i]['popis'];
        bts['cislopopisu']=predchozibtsky[i]['cislopopisu'];
        if predchozibtsky[i]['cas'] > .aktualnicas-.maxminutnanezobrazeni*60 and len(predchozibtsky)-i <= .maxpolozeknanezobrazeni then
          bts['pozicepredtim']=len(predchozibtsky)-1-i;
        end;
        array.remove(predchozibtsky[i]['idbts'],i2);//pak se to da na konec
        return true;
      end;
    end;
  end;
  return false;
end;

predchozibtsky=[];
napsanapredchozi=false;
.staredatum=null;
zmenbtsek=-1; //aby po prvnim cyklu byla nula
caspocitanizmen=null;
do
  aktualnicas=time.get();
  while true do
    try
      if not gsm.new(4500) then
  //trva ~4 vteriny, nez se aktualizuje LAC, cekani na stabilitu
        cid=gsm.cid();
        lac=gsm.net()['lac'];
        break;
      end;
    catch e by
print '#'+e+'#';
      sleep(1000);
    end;
  end;

  //idbts=hexstr(cid,4)+str(lac);
  idbts=cid+'#'+lac;

  bts=[];
  priznakknapsani=null;
  if cid = 0 and lac = 0 then
    priznakknapsani='-';
  else
    zmenbtsek++;
    if not VratZCache(idbts,predchozibtsky,bts) then
      lokace=VratLokaci(cid,lac);

      bts['popis']=lokace['okres']+': '+lokace['popis'];
      bts['cislopopisu']=lokace['cislopopisu'];

      for i=len(predchozibtsky)-1 to 0 by -1 do
        if bts['cislopopisu'] = predchozibtsky[i]['cislopopisu'] then

          if predchozibtsky[i]['cas'] > .aktualnicas-.maxminutnanezobrazeni*60 and len(predchozibtsky)-i <= .maxpolozeknanezobrazeni then
            priznakknapsani=len(predchozibtsky)-1-i;
          end;
          break;
        end;
      end;
    else
      priznakknapsani=bts['pozicepredtim'];
    end;

    if zapisovatposlednibts then
      f=io.create('KyblKdeJsem.txt',io.utf8);
      io.write(f,bts['popis']+' ('+lac+'/'+cid+')');
      io.close(f);
    end;

    zaznam=null;
             //najdu, kde v cache to je
    for i=len(predchozibtsky)-1 to 0 by -1 do
      if bts['cislopopisu'] = predchozibtsky[i]['cislopopisu'] then
        zaznam=predchozibtsky[i];
        array.remove(predchozibtsky,i);    //pak se to da na konec
        break;
      end;
    end;
    if zaznam = null then
      zaznam=['idbts': [], 'cislopopisu': bts['cislopopisu'],'popis': bts['popis']];
      pozicevcache=len(predchozibtsky)-1;
    end;

    zaznam['cas']=.aktualnicas;
    append(zaznam['idbts'],idbts);
    append(predchozibtsky,zaznam);

    while len(predchozibtsky) > .maxpolozeknanezobrazeni and predchozibtsky[0]['cas'] <
.aktualnicas-.minminutvcache*60 do
      array.remove(predchozibtsky,0);
    end;

    if priznakknapsani = null and napsanapredchozi then
      io.print(io.stdout,']');
    end;

    datum=time.str(.aktualnicas,'DD. MM. YYYY');
    if datum # .staredatum then
      if .staredatum # null then
        io.print(io.stdout,'\n\nCelkem za den změněn vysílač '+zmenbtsek+'x (včetně změny kanálu v rámci vysílače), tj. '+math.round(zmenbtsek/((time.get()-caspocitanizmen)/3600),1)+'x za hodinu\n\n');
      end;
      io.print(io.stdout,'==== '+datum+' ====');
      .staredatum=datum;
      zmenbtsek=0;
      caspocitanizmen=time.get();
      if napsanapredchozi then
        io.print(io.stdout,'\n');
      end;
    end;

    if priznakknapsani # null then
      if priznakknapsani # 0 then
        if not napsanapredchozi then
          io.print(io.stdout,'[');
          napsanapredchozi=true;
        end;
        io.print(io.stdout,priznakknapsani);
      end;
    else
      cas=time.str(.aktualnicas,'hh:mm:ss');
      io.print(io.stdout,'\n'+cas+' '+bts['popis']+' ');
      napsanapredchozi=false;
    end;
  end;

  gsm.new();
until false;
