﻿/*
 Automatické vypínání a zapínání zvuku podle času a dne pro m-shell
 Copyleft Aleš Janda, KÝBLSoft 2008
 Více na www.kyblsoft.cz/mobil
 GNU GPL software - užívejte bez omezení ;-)
*/


use app,files,math,phone,sms,time,ui;

 // nastaveni casu, kdy se ma vypnout (a zapnout) zvuk. Zmente podle potreby, nize je priklad
.casyvyp=[
  ['od': 22, 'do': 7],              // kazdy den od 22 h do 7 h
  ['od': 7, 'do': 10.30, 'dny': [2,5,6,7,10], 'dovzbuzeni': true],  // v utery, patek, o vikend a specialni dny s cislem 10 - vypnuti zvuku od 7 do probuzeni cloveka, max. vsak do 10:30
  ['od': 9.15, 'do': 10.50, 'dny': [1,3,4]],  // v pondeli, stredu a ctvrtek vypnout zvuk od 9:15 do 10:50
  ['od': 11, 'do': 12.35, 'dny': [3,4]],   //atd...
  ['od': 12.45, 'do': 15.05, 'dny': [1]],
  ['od': 12.45, 'do': 14.20, 'dny': [2,4]],
  ['od': 14.30, 'do': 16.05, 'dny': [3]],
  ['od': 16.15, 'do': 17.50, 'dny': [3]],
  ['od': 18.00, 'do': 19.25, 'dny': [2,3,4]],
  ['od': 18.08, 'do': 19.45, 'dny': [1]]
];

// nastaveni specialnich dnu, tj. nastaveni chovani ne podle dne v tydnu, ale dne v roce
// Specialni dny by normalne mely mit jine cislo nez 1 - 7. Pokud si vsak prejete chovani typu "tento ctvrtek delam to, co bych normalne delal ve stredu", muzete nejake datum takto nasilne preradit na jiny den
.specialnidny=['10': ['1405',    // vypsani statnich svatku ve formatu DDMM (viz .formatdata nize)
'0101','0105','0805','2810','1711','2312','2412','2512','2612','2712','2812','2912','3012','3112']];


.delkanecinnosti=15;
.formatdata='DDMM';

function PrevedCisloNaCas(hodina)
//9.5 -> 9:30
  
  cela=math.floor(hodina);
  des=hodina-cela;
  des=str(math.floor(des*60));
  if len(des) = 1 then
    des='0'+des;
  end;
  return cela+':'+des;
end;

function PrevedCasNaCislo(hodina)
//prevede desetinnou cast z minut na skutecnou desetinnou cast
  
  cela=math.floor(hodina);
  des=hodina-cela;
  return cela+des/60*100;
end;

function PrevedCasyNaCisla(casyvyp)
//prevede desetinnou cast z minut na skutecnou desetinnou cast

  for i=0 to len(casyvyp)-1 do
    casyvyp[i]['od']=PrevedCasNaCislo(casyvyp[i]['od']);
    casyvyp[i]['do']=PrevedCasNaCislo(casyvyp[i]['do']);
  end;
end;

function PrevedSpecialniDny(specialnidny)
  navrat=[];
  cisladnu=keys(specialnidny);

  for i=0 to len(specialnidny)-1 do
    cislodne=cisladnu[i];
    for den in specialnidny[cislodne] do
      navrat[den]=cislodne;
    end;
  end;

  return navrat;
end;

function JeVypnutyZvuk()
  return files.exists('C:\\Shared\\silentmode.txt');
end;

function UzSeProbudil()
//probuzeni se pozna tak, ze uz neni zadna nova zprava

  while true do
    try
      zpravy=sms.inbox();
      nova=sms.get(zpravy[len(zpravy)-1])['unread'];
      return not nova;
    catch e by
      sleep(500);
    end;
  end;
end;

function VypniZapniZvuk()
  app.show(270555829);  //GDesk
  sleep(1000);
  app.key([25,-25]);   //rozsvitim
  sleep(2000);
  app.key([167,-167]);
          //zavru pripadna oznameni
  sleep(2000);
  app.key([69,-69]);   //e
  sleep(2000);
  app.key(15);    //#
  sleep(1000);
  app.key(-15);
  sleep(3000);
  app.show(3890268855);
end;

function PrepniStavAVratCas(zvuk)
  poccas=time.get();

  pokusu=0;
  while zvuk = JeVypnutyZvuk() and pokusu < 10 do
    pokusu++;

    if zvuk then
      print time.str(time.get(),'hh:mm:ss')+' Zapínám zvuk...';
    else
      print time.str(time.get(),'hh:mm:ss')+' Vypínám zvuk...';
    end;

    phone.state(phone.idle);

    while ui.idletime() < .delkanecinnosti*1000 do
      sleep(.delkanecinnosti*1000-ui.idletime());
      phone.state(phone.idle);
    end;

    VypniZapniZvuk();

  end;

  return (time.get()-poccas)/60/60;
end;

function VratCasDo(hodinated,dohodiny)
  if hodinated <= dohodiny then
    return dohodiny-hodinated;
  else
    return 24-hodinated+dohodiny;
  end;
end;

function TestniCas(casvyp,den,hodina)

  //kontrola dne
  if casvyp['dny'] # null then
    splneno=false;
    for d in casvyp['dny'] do
      if d = den then
        splneno=true;
        break;
      end;
    end;
    if not splneno then
      return ['stav': true, 'platido': VratCasDo(hodina,24), 'dovzbuzeni': false];
    end;
  end;

  //kontrola hodiny
  if casvyp['od'] < casvyp['do'] then
    if hodina >= casvyp['od'] and hodina < casvyp['do'] then
      return ['stav': false, 'platido': VratCasDo(hodina,casvyp['do']), 'dovzbuzeni': casvyp['dovzbuzeni']];
    else
      return ['stav': true, 'platido': VratCasDo(hodina,casvyp['od']), 'dovzbuzeni': casvyp['dovzbuzeni']];
    end;
  else
    if hodina >= casvyp['od'] or hodina < casvyp['do'] then
      return ['stav': false, 'platido': VratCasDo(hodina,casvyp['do']), 'dovzbuzeni': casvyp['dovzbuzeni']];
    else
      return ['stav': true, 'platido': VratCasDo(hodina,casvyp['od']), 'dovzbuzeni': casvyp['dovzbuzeni']];
    end;
  end;
end;

function KdyJePristiAkce(casyvyp,den,hodina)
  cekat=24*60*60;
  zvuk=true;
  dovzbuzeni=false;

  for casvyp in casyvyp do
    stav=TestniCas(casvyp,den,hodina);
    if stav['platido'] < cekat then
      cekat=stav['platido'];
    end;
    if not stav['stav'] then
      if stav['dovzbuzeni'] = true then
        if not UzSeProbudil() then
                //cili podminka plati
          zvuk=false;
          dovzbuzeni=true;
        end;
      else
        zvuk=false;
      end;
    end;
  end;

  return ['stav': zvuk,'cekat': cekat,'dovzbuzeni': dovzbuzeni];
end;

function CekejPoDobu(hodiny)
  while hodiny > 0 do
    cekat=hodiny;

    if cekat > 0.4 then
      cekat=0.4;
    end;

    sleep(cekat*60*60*1000);
    hodiny-=cekat;
  end;
  sleep(100);  //kvuli chybe zaokr.
end;

function CekejPoDobuDoVzbuzeni(hodiny)
  while hodiny > 0 do
    if UzSeProbudil() then
      break;
    end;

    cekat=hodiny;

    if cekat > 0.03 then //1,5 minuty
      cekat=0.03;
    end;

    sleep(cekat*60*60*1000);
    hodiny-=cekat;
  end;
  sleep(100);  //kvuli chybe zaokr.
end;

function VratCisloDne(cas,specialnidny)
 //vrati # svatku nebo den v tydnu

  den=time.str(cas,.formatdata);
  if specialnidny[den] # null then
    return num(specialnidny[den]);
  else
    return time.dayofweek(cas)+1;
  end;
end;

PrevedCasyNaCisla(casyvyp);
specialnidny=PrevedSpecialniDny(specialnidny);

while true do
  cas=time.get();
  den=VratCisloDne(cas,specialnidny);
  hodina=num(time.str(cas,'hh'));
  hodina+=num(time.str(cas,'mm'))/60;
  hodina+=num(time.str(cas,'ss'))/3600;

  akce=KdyJePristiAkce(casyvyp,den,hodina);

  akce['cekat']-=PrepniStavAVratCas(akce['stav']);
  if akce['cekat'] > 0 then
             //muze byt uz lehce pod
    hlaska=time.str(time.get(),'hh:mm:ss')+' Čekám '+PrevedCisloNaCas(akce['cekat'])+' hod';
    if akce['dovzbuzeni'] then
      print hlaska+' na vzbuzení';
      CekejPoDobuDoVzbuzeni(akce['cekat']);
    else
      print hlaska;
      CekejPoDobu(akce['cekat']);
    end;
  end;
end;