Labai paprasti PHP šablonai

Šiandien kažkas PHP konferencijoj išreiškė mintį, kad kiekvienas save gerbiantis PHP programuotojas turi būti pasirašęs savo lankytojų skaitliuką, duomenų bazės abstrakcijos klasę ir šablonų klasę. Na, skaitliukas turbūt lengviausia :) Duomenų bazės šiokią tokią abstrakciją irgi esu rašęs, šablonus taip pat, tad turbūt galiu prisirašyti save prie tų „save gerbiančių PHP programuotojų“ ;)

Tiesa, jokiu būdu nesu šablonų ekspertas. Teko man naudotis tik pukomuko phemplate, bei savo kurtais šablonais (kurie dabar šiek tiek juokingai atrodo, mat rašiau lygiai prieš metus. Metai programavimo suteikia daug žinių ;). Vienintelis dalykas, kuris man nepatinka phemplate yra tas kad tie šablonai ganėtinai neintuityvūs ir sudėtingi naudoti (suprantu, kad tai kodo greičio sumetimais) palyginus su Perlo HTML::Template, kurią pastaruoju metu naudoju dažniausiai. Ten labai man patinka tai, kad užtenka „pririšti“ masyvą prie šablono ir visi šablono parametrai bus imami būtent iš šio masyvo. Tai labai praverčia validuojant formas: automatiškai pririši per POST gaunamų reikšmių masyvą su šablonu ir nereikia kiekvienam laukui nustatyti atskiro kintamojo. Panašiai galima padaryti ir su iš duomenų bazės gaunamais duomenimis: dvimatį iš duombazės gaunamą masyvą pririši prie šablono ciklo <LOOP> ir duomenys automagiškai susidėlioja į vietas. Aišku tam nebūtinai reikia „pririšimo“, juk galima tiesiog perduoti šablonui visą masyvą ir tiek, tačiau „pririšimas“ suteikia gana įdomių savybių, kurios galbūt kažkam gali būti labai naudingos (pirmas didelis pliusas yra greitis, kadangi perduodamas ne visas masyvas, o tik nuoroda į jį).

Žodžiu visas šitas kodas kol kas yra „proof of concept“, nes realaus pritaikymo dar nelabai sugalvojau šitam „pririšimui“ ;)

Pirmiausia pasirašiau labai primityvią šablonų klasę, kuri sugeba pakeisti tik <VAR vardas> ir išsaugojau kaip sablonas.php:

<?php
class sablonas
{
        var $out = '';
        var $vars = array();

        function sablonas($byla = 'index.html')
        {
                if(is_file($byla)) {
                        $this->out = implode('', file($byla));
                } else {
                        die("Nera tokios bylos '$byla'");
                }
        }

        function tie(&$masyvas)
        {
                $this->vars = &$masyvas;
        }

        function output()
        {
                while(($pos = strpos($this->out, '<VAR ')) !== false) {
                        $varlength = strpos($this->out, '>', $pos) - $pos;
                        $varname = substr($this->out, $pos + 5, $varlength - 5);
                        $this->out = substr($this->out, 0, $pos) . 
                                htmlspecialchars($this->vars[$varname]) . 
                                substr($this->out, $varlength + $pos + 1);
                }
                return $this->out;
        }

}
?>

Vienintelė magija čia atliekama funkcijoje tie(), kur $this->vars yra priskiriamas $masyvas adresas. Faktiškai Perle tai prilygtų typeglobų sulyginimui (*vars = *masyvas). Po šio sulyginimo tiek $this->vars, tiek $masyvas rodo į tą patį įrašą simbolių lentelėje (ar kaip tas daiktas PHP vadinasi… čia gal kiek per daug Perl terminologiją taikau ;) Žodžiu esmė tame kad tie patys duomenys gali būti pasiekiami dviem vardais.

Pasirašiau paprastą šabloną index.html:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> Pavadinimas </TITLE>
</HEAD>
<BODY>
<FORM ACTION="test.php" METHOD="POST">
<P><B>A:</B> <INPUT TYPE="TEXT" NAME="a" VALUE="<VAR a>"></P>
<P><B>B:</B> <INPUT TYPE="TEXT" NAME="b" VALUE="<VAR b>"></P>
<INPUT TYPE="HIDDEN" NAME="count" VALUE="<VAR count>">
<P><INPUT TYPE="SUBMIT"></P></FORM>
<P>Forma rodoma kartu: <VAR count></P>
</BODY>
</HTML>

O štai ir test.php:

<?php
include 'sablonas.php';
$foo =& new sablonas();
$foo->tie($_POST);
$_POST['count']++;
print $foo->output();
?>

Tas $_POST['count']++ atrodytų jog vyksta jau PO masyvo perdavimo šablonui, bet šablone šie pokyčiai irgi atsispindi, mat perduodami ne duomenys, o tik nuoroda į juos. Kadangi $_POST[] surišama su šablonu, tai šablone formai be didelių vargų suteikiamos tokios reikšmės, kurios jau ir buvo perduotos.

Ech, man aišku tokiais eksperimentais pasireškia IRC trūkumas turbūt. Visiškai nenaudinga, bet bent jau man įdomu. Ir aišku nesu PHP guru – tuoj kas nors komentaruose kokį nors geresnį būdą automatiniam formų pildymui. Vat automagiškai susieti šabloną su SQL selectu būtų žymiai įdomiau ir naudingiau, bet dabar reik eit civilinės ir darbo teisės mokytis

Ekstremalus programavimas su PHP

Prisiskaičiau daug visokių dalykų apie ekstremalų programavimą. Kaip žinia, ten labai svarbus programų testavimas. Faktiškai viena svarbiausių idėjų yra „pirma parašyk neveikiantį testą, paskui tik pakeisk programą, kad tas testas veiktų“. Šitaip testuojant kiekvieną programos gabaliuką galima užtikrinti kad programa veiks taip kaip buvo planuota ir liks mažiau nesugaudytų vabaliukų.

Ant mano mylimojo Perl yra toks modulis Test::Simple (teko netgi girdėti kad Perlas turi vieną geriausių testavimo įrankų rinkinį – panašus yra lyg tik Javos JUnit). Na Test::Simple idėja yra labai paprasta, tad persirašiau kažką labai panašaus ir PHP kalba:

<?php
# PHPinis Test::Simple ;)
class TestSimple {

        var $count = 0;
        var $failed = 0;
        var $options = array('dont_print_ok' => false);

        function TestSimple($options = NULL)
        {
                $this->options = array_merge($this->options, $options);
        }

        function ok($code, $failure_message = 'No reason given<br>') 
        {
                $this->count++;
                if($code === true) {
                        if($this->options['dont_print_ok'] === false) {
                                print("OK $this->count<br>");
                        }
                } else {
                        $this->failed++;
                        print("Failed $this->count: $failure_message<br>");
                }
                return $code;
        }

        function result() 
        {
                if($this->failed) {
                        print("Failed $this->failed tests out of $this->count<br>");
                } else {
                        print("All $this->count tests successful<br>");
                }
        }

}
?>

Naudojimasis šia klase, kaip ir visas testavimas yra labai paprastas. Pats paprasčiausias testavimas (nenaudojant jokios klasės) būtų panašus į šį:

<?php if(2 * 2 == 4) { print "OK"; } else { print "Not OK"; } ?>

Tiek Test::Simple, tiek ši PHPinė klasė šiek tiek palengvina testavimą. Naudojantis šia klase būtų galima parašyti analogišką testą:

<?php $test->ok(2 * 2 == 4); ?>

Apskritai apie testavimą gana neblogai parašyta Test::Tutorial Perliniame modulyje.

Funkcinis programavimas su Haskell

Vat šiandien truputį skaitinėjausi apie Haskell
programavimo kalbą. Tai grynai funkcinė programavimo kalba (faktiškai
pati įdomiausia dalis ten apie tai kas yra funkcinė programavimo
kalba) ir bent jau man truputį priminė LISP tik be skliaustelių (na..
aišku priminė tik dėl Lambda funkcijų ir dėl to kad ten kintamųjų
priskyrimas neturi reikšmės atrodo ;)

Vat quicksort algoritmas Haskeliu:

qsort []     = []
qsort (x:xs) = qsort elts_lt_x ++ [x] ++ qsort elts_greq_x
                 where
                   elts_lt_x   = [y | y <- xs, y < x]
                   elts_greq_x = [y | y <- xs, y >= x]

Tiesą sakant kodas skaitosi gana lengvai jei šiek tiek matematikos
mokaisi. Bet man dar tas visas programavimas tik per aibes ganėtinai
keistas atrodo. Per daug esu įpratęs mąstyti neLISPiškai :)

Perkrauta matrica: kompiuterastinis požiūris

Šį penktadienį, atsiklausęs #php kanalo ar niekas neina gerti, supratau kad teks vakarą planuotis kažkaip pačiam. Kadangi vis dar prisilaikau „jokio IRC“ politikos, tai nutariau nueiti į kiną ir pažiūrėti perkrautą matricą. Tai jeigu dar nematėt šio filmo ir nenorit sužinot jo detalių, tučtuojau baikit skaityt.

Jei jūs vis dar čia, reiškia norit pasiskaityti mano nuomonę apie filmą. Aš, kaip ir visi (ok, ne visi… pukomuko yra kitos nuomonės) esu nusivylęs filmu. Na, tarkim jei nebūtų buvę pirmos matricos ir jei nebūtų tiek daug reklamos ir panašiai, tai galėčiau filmui duoti kokius 6 balus. Stiprus vidutiniokas.

Pati didžiausia filmo problema mano nuomone yra ta, kad jis tapo specialiųjų efektų paroda. Jie naudojami kur reikia ir kur nereikia. Labai greitai darosi nuobodu. Neo mušasi savo kong-fu stiliumi kas 15-20 minučių ir aišku laimi. Na bet po antros panašios kovos būtų gal galima ir ką nors naujo sugalvot? Šiaip man patiko agento Smito dauginimosi idėja (apie idėjas šiek tiek vėliau ;) bet jos realizacija tikrai nieko gero. Pirmoj matricoj Smitas buvo labai galingas, visi jo bijojo, jis buvo vertas priešininkas pačiam Neo. O čia jis atrodo lyg vaikas, Neo jį galėtų primušti užmerktom akim ir dar tuo pačiu metu tikrindamasis naujausią interneto pornografiją. Tiesiog nelieka intrigos kai Neo laimi. Ir dar kartą laimi. Ir vėl laimi. Ir vėl. Ech…

Kame ten bajeris su Trinity ir Neo meile? Nuo kada kompiuterastai myli? Na, jei reikia labai tos meilės tai bent sekso sceną normalią padaryt :/ Pravalas kažkoks. Su ta meile te dar visokių nesąmonių mano nuomone yra. Morpheus ten irgi myli Naobi ar kaip ten ją ir dėl to ji atvyksta į pagalbą. Nu kažkokia saldi meksikietiška melodrama gaunasi. Hey, juk mes čia susirinkom hakint matricos, o ne meilių seilių žiūrėt, po velnių!

Vat dabar apie pačią filmo idėją. Šis filmas irgi turi idėją. Tik ji visiškai užgožta spec. efektų, bereikšmių scenarijaus nukrypimų, meilių, ir dar velnias žino ko. Ir pati ta idėja nėra tokia stipri ir galinga. Tiesa, mano nuomone filmo idėja buvo šiek tiek kitokia nei turbūt kūrėjai norėjo parodyt eiliniam žiūrovui (na aš kompiuterastas gi ;) Faktiškai filmo idėja rutuliojasi apie predeterminizmą ir ar žmogus gali keisti lemtį. Tai čia oficiali idėja ;)

Man aišku pati geriausia vieta filme buvo Architekto kalba. Architektas yra tas žmogus kuris suprogramino ir sukūrė matricą. Toje kalboje jis faktiškai paaiškina kaip jis ją kūrė ir kokios problemos buvo su tuo susijusios. Vat iš čia aš ir sumąsčiau savo matricos filmo idėją.

Žodžiu esmė tame kad matrica yra didelis kompas. Na, operacinė sistema tarkim. Architektas yra programeris. Labai geras ir protingas programeris. Tiesą sakant aš į Neo žiūriu kaip į paprastą script kiddie: na, jis ten moka fainai skraidyt ir gerai kovot ir panašiai, bet jis nesupranta kam visa tai. Jis neturi tikslo. Čia lyg galėtum root‘int sistemą be didelio vargo, bet to juk neužtenka. Realiai jis neturi priėjimo prie sourcų (filme gi lyg buvo į tai atsižvelgta: tipo visa šio filmo esmė kad Neo turi dasikast prie sourcų). Net jei ir turėtų kažkaip abejoju ar jis žinotų ką su jais veikt. Kompiliatoriaus reik. reik mokėt skaityt kodą ir patčint. Reik mokėt RTFM’intis (nu o jis gi nieko neveikia tik skraido iir mylisi su Trinity ir dar nešioją tą keistą švarką/sutaną). Tiek pokalbyje su MySQL, tpfu, Oracle, tiek su Architektu, tiek dar su tuo prancūzišku daiktu Neo atrodo visiškai žalias. Primena kai kuriuos žmones iš #php, kurie klausia kas yra kintamasis. Bet Neo moka hakint. Na… naudotis exploitais, kuriuos turbūt ne pats ir surado. Tai tokia mano nuomomnė apie Neo :)

Trinity tai irgi tas pats. Tik dar mažiau suvokianti kas čia vyksta. Morpheus tai Linux fanatikas, kuris pats irgi neprogramina. Kliedi apie tai kad viskas turi būt laisva ir panašiai. Realiai antram filme jis jokio ten perdaug svarbaus vaidmenio nevaidina. IMHO aišku.

Agent Smith vat fainas white-hat vyrukas. Jis supranta, kad Neo yra nieko gero, bet jam pačiam trūksta žinių. Na, jis tik adminas gi. Irgi neprogrameris. Tas savęs dauginimasis tai visai gera DDOS ataka prieš Neo, tik Neo turbūt gerą firewallą turi.

Vat Architektas yra pats geriausias ir protingiausias tame filme. Žodžiu visas tas sourcų dalykas pasirodo yra honeypotas, kurį jis padarė kad sugaudytų tuos visokius skript kiddies kaip Neo. Esmė paprasta: kai Neo galvoja kad jis krūtas skraidydamas ir darydamas visokias kitokias nesąmones, Architektas logina visą trafiką, disasemblina Neo kodą ir paksui užpatčina matricą. Standartinis programų kūrimo procesas. Man dar patiko tas Neo pokalbis su Architektu nes ten lyg Architektas būtų pasileidęs debugerį ant visų ekranų ;) Na taip, aš kompiuterastas ;)

Kursiniai, Google ir IRC

Na vakar lyg baigiau rašyti kursinį, šiandien priduot jį reikia :)
Nors kursinis turėjo būti iš finansų srities, ganėtinai nemažai ten
gavosi ekonometrijos ir matematinių skaičiavimų (man kažkaip labiau
patinka kai yra krūva mažai kam suprantamų formulių ir statistinių
tekstų, o ne daug priskiesta pliurpalizmų)

Šiandien darbe pasižiūrėjau kaip lietuvoje.lt serverį suranda
google. Atrodo prisidirbau – daugiausiai lankytojų iš
google mane pasiekia įvedę paieškoje „decode iso 8859 c#“.
Žodžiu kažkaip lyg ir tapau priešingos C# stovyklos pagalbos šaltiniu
(nors aišku čia atėję, jeigu jie supranta lietuviškai, randa tik Perlo
kodo gabaliuką, kuris turėtų išspręsti jų problemą ;) Jaučiuosi kažkaip
netyčia populiarinantis Perlą šituo (man irgi yra teką kartais ieškotis
sprendimo būtent kažkokia kalba, o rast tik būtent kitokios kalbos
sprendimus – tai kartais padeda apsipręsti ir pakeisti naudojamą
technologiją)

Kol kas ir toliau sėkmingai gyvenu be IRC. Lyg didelių psichologinių
traumų kol kas nepatyriau ;)

Išinstaliavau XChat

Bandydamas pažaboti savo laiko švaistymą sesijos metu, šiandien
išinstaliavau visus IRC klientus bei darbe užblokavau 6667-6668
portus. Tad manęs nematysit IRC porą savaičių (išskyrus
savaitgaliais…) Tikiuosi tai pagerins mano motyvaciją rengiantis
egzaminams :)

Einu skaitytis apie SODROS biudžeto sudarymo ir tvirtinimo procesą
:/

Perl/CGI vs PHP

Perlmonks vėlgi turi šaunų threadą apie Perl/CGI vs
PHP
. Šį kartą jis pasižymėjo gana įdomiais posakiais (na, ko gi
tikėtis, juk perlo fanatikų klausia nuomonės ;)

Every PHP geek will claim PHP is better for so many
reasons, but every perl geek knows better.

PHP as a language is basically Perl with all the fun parts
taken out

PHP is easier to learn, Perl is easier to get things done
with.

PHP was made by someone who knew, but clearly didn’t fully
understand Perl.

Darbai, mokslai…

Nagi prasidėjo sesija. Be to ir darbai nesibaigia. Tai reiškia, kad
aš čia per daug nesireikšiu kokias porą savaičių.

Beje, prašė manęs šiandien parašyti perlinę programėlę, kuri
išrinktų visas šių metų dienas, kur yra savaitgaliai. Didžiausias
klausėjo nustebimas buvo tas, jog jei pateiki funkcijai
Date::Calc->Day_of_Week() blogai suformuotą datą
(tarkim 20012 metų 15 mėnesio 89 dieną) tai ji nesikeikia. Na,
funkcija tokiu atveju grąžina 0, kai normliai grąžint turi nuo 1 ki 7,
tad jei nori ieškotis errorų, gali juos rast. Matyt tas žmogus visai
Perlo neragavęs (netgi turbūt skriptinių programavimo kalbų irgi
nelabai matęs) kad jį tokie dalykai stebina. Štai kodas (hmmm.. reikia
kažkokį Perlo kodo archyvą kurt ;):

use Date::Calc qw/Day_of_Week/;
my @menesiai = qw/sausio vasario kovo balandžio gegužės birželio
               liepos rugpjūčio rugsėjo spalio lapkričio gruodžio/;
for my $menuo (1..12) {
  for my $diena (1..31) {
    my $d = Day_of_Week(2003, $menuo, $diena);
    if($d == 6 or $d == 7) {
      print($menesiai[$menuo - 1], " $diena\n");
    }
  }
}

Oh, beje turbūt šitas pavyzdys kartu ir įrodo jog Perlo kodas
gali būti ir įskaitomas ;)

Optimizavau Ruby

Visgi nesinorėjo tikėti, kad Ruby toks lėtas, todėl pasiskaičiau manualą. Pirma, susitvarkiau su tuo nil. Pasirodo, užteko nurodyt reikšmę pagal nutylėjimą (hmmm… įdomu tokie bajeriai kitose kalbose iš vis yra?). Paskui ir patį kodą perrašiau truputį panašiau į Ruby kodą ;) Rezultatas aiškus: kodas sutrumpėjo iki kokių 6 eilučių (atkaklios rungtynės su Perlu ;), o kodo greitis padidėjo penkis (!) kartus. Tiesa, algoritmas šiek tiek pasikeitė. Reikės tuo pačiu algoritmu ant PHP ką nors pabandyt. O juk atrodytų skaityt iš bylos po baitą yra labai lėta…

t = "%10.5f" % Time.now.to_f
h = {}; h.default=0;
File.new($*[0]).each_byte { |char| h[char] += 1 }
h.each { |k, v| print "#{k.chr} => #{v}\n" }
print "Laikas: ", (("%10.5f" % Time.now.to_f).to_f - t.to_f).to_s

Vykdymo greitis su 1.5MB tekstine byla: 12.708 sekundės (Perlas – 13.690)

Perl vs PHP vs Ruby

Taip jau visad gaunasi kad kai reikia mokytis tai darai bet ką, tik ne mokaisi. Tad šiandien padariau dar vieną benchmarką, kuris gal būt bus įdomus ir kitiems.

Problema tokia: reikia programos, kuri nuskaitytų bylą ir suskaičiuotų kiek yra skirtingų simbolių (tarkim „a“ – 152 kartai, „b“ – 189, ir panašiai). Algoritmas paprastas ir visur vienodas: nusiskaitom bylą po eilutę, skaidom į simbolių masyvą, pereinam per šį masyvą, padidindami atitinkamas reikšmes saugomas asociatyviajame masyve (jei skamba sudėtingai, tai žiūrėkit kodą, ten aiškiau ;)

Pirmiausia parašiau Perlinį variantą. Užtruko apie 2-3 minutes (rašymo trukmė maža, nes Perlas man gerai žinomas, nereikia per daug nieko galvoti, esu prie jo pripratęs):

use Time::HiRes qw/gettimeofday tv_interval/;
my $t0 = [gettimeofday];
while(my $h = <>) { $_{$_}++ for split //, $h; }
print "$_ => $_{$_}\n" for keys %_;
print "Laikas: ", tv_interval($t0, [gettimeofday]);

Eilučių skaičius – apie 5 (sakau „apie“, nes ciklus galiam skirti ir kaip atskiras eilutes. Čia priklauso nuo to ką laikote eilute. Ilgiausiai laiko rašant užtruko modulio Time::HiRes dokumentacijos pasižiūrėjimas, nes jo dažnai nenaudoju (be to, jis čia atlieka pagalbinę laiko skaičiavimo funkciją)

Toliau parašiau PHP programėlę (kuri eitų per CLI). Užtruko apie 10 minučių, dėl poros priežasčių. Pirma, reikia spausdinti šiek tiek daugiau kodo, antra, buvau nustebęs kad explode negali veikti su tuščiu stringu (explode('', $foo) meta klaidą). Nuėjau pasiskaityti dokumentacijos, bet lyg neradau kitos alternatyvos preg_split. Štai PHP variantas:

<?php
function getmicrotime() { 
    list($usec, $sec) = explode(' ',microtime()); 
    return ((float)$usec + (float)$sec%10000); 
    } 
$time_start = getmicrotime();

$f = fopen($argv[1], 'rb');
while (!feof ($f)) {
    $m = preg_split('//', fgets($f, 4096));
    foreach ($m as $v) {
        $res[$v]++;
    }
}
fclose($f);
foreach($res as $k => $v) {
        print "$k => $v\n";
}
print "Laikas: ".(getmicrotime()-$time_start);
?>

Eilučių: apie 11. getmicrotime() funkcija paimta tiesiai iš manualo.

Įkvėptas greitos sėkmės sugalvojau kad reikia pabandyti parašyti ir Ruby programą. Vat čia užtrukau. Kokias 40 minučių. Ruby aš žinau šiek tiek tik teoriją, ir tai seniai ją skaičiau, todėl teko paskaityti dokumentaciją. Be to, mano Ruby programa, nors ir veikia, atrodo labai keistai, labai jau perliškai. Įtariu jog Ruby prastas pasirodymas benchmarkuose yra tiesiog mano kreivų rankų produktas. Štai rubinas:

t = "%10.5f" % Time.now.to_f
f = File.new($*[0])
h= {}
f.each { |line| 
    line.split(//).each { |char|
        h[char] = h[char].to_i+1;
    }
}
h.each { |k, v| print "#{k} => #{v}\n" }
print "Laikas: ", (("%10.5f" % Time.now.to_f).to_f - t.to_f).to_s

Eilučių: apie 8. Labiausiai keistas dalykas, kuris turi daug reikšmės benchmarke, ir kuris tikrai kažkaip kitaip turėtų būt išsprendžiamas yra tas, kad nil kažkodėl negalima automatiškai pasiversti į skaičių „0“. Įtariu kad reikia apsirašyt savą metodą vienos eilutės tam. Be to labai bjauriai su tais laiko matavimais ir tipų keitimais gaunasi :/ Matyt aš ten dar visai kampo nepagavęs esu ;)

Pats benchmarkas buvo atliekamas su 1,5MB tekstine byla (#php kanalo logas ;). Rezultatai (sekundėmis): Perl 13.6896, PHP 27.4513, Ruby 61.4180

Ką tai reiškia? Visiškai nieko. Perlas greitesnis, nes čia ir yra jo pritaikymo sritis. Perlas čia dar greitesnis ir dėl to, kad aš jį geriau moku nei kurią kitą kalbą. Tad jei esate PHP diveas, o Perlo visai nemokat tai jokiu būdu neapsimoka jums mesti PHP – tai labai gerai iliustruota mano bandymais rašyti Ruby kalba (kituose normalių žmonių benchmarkuose Ruby greičiu prilygsta Perlui). Ruby programa ne tik lėčiau veikė, bet dar ir aš ją rašiau žymiai ilgiau.

Faktiškai visa šitai tik parodo kad MAN Perlas yra geriausias pasirinkimas, galbūt jau vien dėl to, kad aš jį moku geriausiai. (Juk sakiau kad stengsiuos atsikratinėt fanatizmu ;)