Dawno nic nie pisałem. Lipiec upłynął miło, bo z dala od zwykłego świata, do dziś sierpień mijał pod znakiem nudy. Dziś postanowiłem wyjebać Archa (zaczynał się sypać) i zainstalować Slackwarea. Od razu znalazło się zajęcie i jest fajnie. Do tego słucham właściwie dwóch kawałków na okrągło, którymi chciałbym się podzielić.
Pierwszym z nich jest utwór Dub Fxa (który urzekł mnie swoim występem na Przystanku Woodstock) pod tytułem "Time Will Tell". Nie jest to ta euforia co na Woodstocku (o którym, mimo, że był moim pierwszym i był świetny, nie chciało mi się napisać ;p), ale i tak jest nadzwyczajny (nie oszukujmy się, nie wiele rzeczy dorównują takiemu koncertowi). Można posłuchać na: http://dubfx.bandcamp.com/ . Tak na marginesie cała płyta jest warta przesłuchania, a nawet kupienia (choć 14 euro to trochę sporo). Warto również zaznaczyć, że wszystko oprócz wokalu i saksofonu na tej płycie to beatbox (oprócz saksofonu) posklejany cyfrowo w pętle i zmiksowany. Koleś zdołał to robić na żywo przed paroma setkami tysięcu ludu.
Drugi kawałek jest jednym z tych które mają świetny rerfren, który przesłania całą resztę. Właściwie jeszcze nie zdąrzyłem się wsłuchać w resztę utworu, ale cóż, takie życie. Utwór pochodzi z albumu pod tytułem "Propaganja - Diss na rząd" nosi tytuł "A ty nie!" i nie pozwala mi nie zacieszać słysząc go. Płytę można znaleźć do ściągnięcia za darmo, a posłuchać na Youtube : http://www.youtube.com/watch?v=0gkxkf_KXu4 . Warto zauważyć, że płyta, choć trochę nazbytyt hip-hopowa jak na mój gust (poprzednia była bardziej reggae), jest godna uwagi.
Czasami (może nawet trochę częściej) jeśli ściąga się filmy i napisy osobno występuje problem synchronizacją. Strasznie upierdliwa sprawa. Oczywiście zwykle jest to proste przesunięcie, w całym filmie, lub na przykład po każdej przerwie na reklamy, więc wystarczy trzymać paluchy na z i x (oczywiście, o ile używa się mplayera). Jest to oczywiście półśrodek, zwłaszcza jeśli owe filmy archiwizujemy i/lub dzielimy się nimi z innymi. Dlatego też napisałem prosty plugin dla vima, który pozwala bardzo łatwo i przyjemnie (najlepiej w połączeniu z mplayerem, w którym można łatwo kontrolować numer odtwarzanej w danym momencie klatki) poradzić sobie z problemem napisów pojawiających się za wcześnie lub za późno.
" Submaker -- video subtitle editor ver 20090611 - early one
" (c) by Bartosz Pastudzki 2009
" I wrote this file. As long as you retain this notice you can do whatever you
" want with this stuff. If we meet some day, and you think this stuff is worth
" it, you can buy me a beer in return.
" Split subtitle line into list of content : [start,end,text]
function SplitLine (line)
let cline = getline (a:line)
let start = match (cline, "{")
if (start == -1)
throw "start1"
endif
let end = match (cline, "}", start)
if (end == -1)
throw "end1"
endif
let subStart = str2nr (cline[start+1 : end-1])
if (start == -1)
throw "start2"
endif
let start = match (cline, "{", end)
let end = match (cline, "}", start)
if (end == -1)
throw "end2"
endif
let subEnd = str2nr (cline[start+1 : end-1])
let content = match (cline, '\S', end+1)
return [subStart, subEnd, cline[content :] ]
endfunction
" Function opposite to SplitLine -- create valid subtitle line from content list
function JoinContent (content)
return "{". a:content[0] . "}{" . a:content[1] . "}" . a:content[2]
endfunction
" Function to find out if subtitle file is valid
function Validate ()
for lineNum in range (1,line ("$"))
try
call SplitLine (lineNum)
catch /.+/
return lineNum
endtry
endfor
return -1
endfunction
" Low level version of Delay. It takes numbers of lines too. It's not intended
" to be called directly by user.
function DelayLL (delay, start, end)
for line in range (a:start,a:end)
let content = SplitLine (line)
let content[0] += a:delay
let content[1] += a:delay
let nline = JoinContent (content)
call setline (line, nline)
endfor
endfunction
" Delay selected part of text
function DelayS (delay)
call DelayLL (a:delay, a:firstline, a:lastline)
endfunction
" Standard delay, from current line to the end
function Delay (delay)
call DelayLL (a:delay, line ("."), line ("$"))
endfunction
function GoToFrame (frame)
let linenum = 0
while 1
let linenum += 1
let last = SplitLine (linenum)
if (last[1] >= a:frame)
break
elseif (linenum == line ("$"))
break
endif
endwhile
call setpos (".", [0,linenum,1])
endfunction
Aby móc używać go w dowolnym momencie, należy zapisać go na dysku, w odzielnym pliku i do pliku .vimrc dodać linijkę "source ". Funkcjami, które służą do używania z zewnątrz są Delay, DelayS i GoToFrame.
Funkcja Delay opóźnia wszystkie napisy od linii w której znajduje się kursor do końca. Na przykład wywołanie ":call Delay (-5)" przesunie je o 5 klatek w tył.
Funkcja DelayS działa tak samo jak Delay, z tą różnicą przesuwa tylko te zaznaczone.
Funkcja GoToFrame przesuwa kursor do linijki, w której znajduje się napis, który się wyświetli się w klatce podanej w parametrze bądź następnego, jeśli w tej klatce nie ma żadnego napisu.
Należy zaznaczyć, że program działa tylko dla napisów w formacie "{start}{koniec} napis" i nie zadziała poprawnie jeśli liczba klatek przekroczy zakres 32-bitowej liczby ze znakiem (231).
Mam nadzieję, że komuś się przyda, będę wdzięczny za wszelkie uwagi i sugestie, ewentualnie łatki.
Już od dłuższego czasu używam LaTeXa i bardzo sobie go chwalę. W sumie, myślę, że chyba nikogo kto miał przyjemność z tego narzędzia korzystać, nie trzeba przekonywać o jego licznych zaletach. W tym semestrze jeszcze częściej go używam, ze względu na sprawozdania z laboratoriów z miernictwa. Nie dbam o to jak to robią inni, ale ja sobie cenię estetykę dokumentów (trzeba się naprawdę postarać, żeby LaTeX coś złożył brzydko) i bardzo wygodne składanie wzorów matematycznych, tudzież wcale niezły system referencji. Jest jednak luka w funkcjonalności (oczywiście nie uważam, że to źle, przeciwnie) LaTeXa jaką odczułem przy okazji pisania wspomnianych sprawozdań, nie daje dobrego sposobu na generowanie wykresów. W tym miejscu z pomocą przychodzi GNU R.
GNU R stanowi bardzo dobre uzupełnienie dla LaTeXa, głównie dlatego, że i ten opiera się o napisanie paru linijek kodu na podstawie którego można wygenerować żądany wykres w jednym z kilku dostępnych formatów (między innymi svg, png). Można też po prostu wyświetlić ten wykres na ekranie. Jak dla mnie to świetna sprawa.
Prosty wykres to kwestia paru linijek, na przykład:
png(file="test.png", width=400, height=400) ib <- seq(50,300, by=50) delta <- c(5.7, 5.3, 3.68, 3.24, 3.30, 1.93) plot(ib, delta, xlab="Ib[mA]", ylab="Bład względny[%]") abline(6.45, -0.015)
W sumie wszystko właściwie widać. Określamy output (plik.png). Tworzymy dwie listy (ib i delta) które wykorzystamy jako współrzędne dla naniesionych punktów. W pierwszym przypadku użyta została funkcja seq(x,y, by=z), która zwraca tablicę elementów od x do y co z. W przypadku delta użyłem funkcji c(e1, e2, e3, ..., en), która po prostu tworzy tablicę z danych argumentów. W następnej linijce jest funkcja plot, która rysuje wykres z naniesionymi punktami, których kolejne współrzędne x są wzięte z ib, a współrzędne y z delta. Dalej znajdują się jeszcze opcjonalne wartości xlab i ylab zawierające opisy osi. Pominięto też parametr, którym można ustawić, by punkty były połączone łamaną. Na sam koniec rysuję prostą przy pomocy funkcji abline, która jest nieco nieintuicyjna ze względu na to, że przyjmuje wartość y dla x = 0 i współczynnik kierunkowy, niezależne od skali i przedziałów jakie będą przyjęte dla poszczególnych osi, ale w sumie to dobrze, że tak jest.
W wyniku przetworzenia takiego kodu otrzymamy coś takiego:

Jest to oczywiście kwestia gustu, ale jak dla mnie jest to rozwiązanie szybsze, wygodniejsze i łatwiejsze w modyfikacji od konkurencji, dajmy na to Microsoft Excel.
Oczywiście jest to bardzo mała cząstka możliwości tego narzędzia (szczerze mówiąc sam ledwo je poznałem ;)), można wygenerować całą masę fajnych wykresów (tu odsyłam do polecenia demo(graphics) w interpreterze GNU R, który pokaże kilka wykresów – takich już pro, nie to co ja wam zaserwowałem ;p – wraz z kodami źródłowymi). To by było na tyle, ale jednak tekst ten powstał jedynie po to by zasygnalizować, że taka zabawka istnieje i nie jest zbyt popularna, a przecież bywa dość przydatna.
O tym, że Windows nie grzeszy wydajnością wiadomo od dawna. Widać to zwłaszcza na moim nieco starym sprzęcie, na którym nawet Windows XP z SP2 i antywirusem nie chodzi zbyt płynnie, na którym Linux pozwala oszczędzić bluzgania na sprzęt. Kolejną rzeczą która dostarczyła mi danych na temat wydajności obu systemów jest fajny FPS pod tytułem Nexuiz - Jak kiedyś próbowałem na Windowsie, niezależnie od ustawień grafiki, gra chodziła płynnie tylko do momentu w którym się pojawiał jakiś przeciwnik (czyli tak trochę kicha). Na każdym unix-like'u na którym próbowałem tej gry da się grać właściwie bez ścinania.
Dziś natomiast w newsletterze z gram.pl zauważyłem, że za 18 złotych można kupić World of Goo (swoją drogą, nie rozumiem ludzi, którzy kradną fajną taką grę mimo niskiej ceny). Patrzę na wymagania sprzętowe. Trochę kiepsko, bo one przewyższają mój sprzęt prawie dwukrotnie, na zalecane Pentium 4, 2GHz z 1GB RAM i kartą graficzną 128MB, AMD XP 1700+ (1GHz), 512 MB RAM i GeForce 2 to jednak trochę mało. Pomyślałem sobie, że i tak ściągnięcie demka nic mnie nie kosztuje. Tak też zrobiłem i się załamałem, bo gra chodzi wcale płynnie.
No nic, wracam do gry, bo zaczyna mnie wciągać. :)
Ostatnio, szwendając się po kolporterze, natrafiłem na kilka pozycji tego autora, obok Serii Patroli Siergieja Łukianienki, która przypadła mi do gustu, toteż postanowiłem spróbować i zakupiłem książkę pt. "Strefa Sprawiedliwości" ("Зона справедливости") i przeczytałem. Tekst ten piszę ze względu na to, że w polskim internecie w zasadzie nie widziałem żadnych opinii na temat książek tego autora.
Strefa sprawiedliwości jest książką, której najbliżej jest do fantastyki, aczkolwiek jednocześnie bardzo ciężko zaliczyć ją do tego gatunku, gdyż jedynym elementem fantastycznym są niewyjaśnione wydarzenia, które są właściwie tłem dla opisywanych wydarzeń. Odnoszę wrażenie, że są one tylko pretekstem do pokazania pewnych cech narodu rosyjskiego.
Powieść opisuje wydarzenia związane z tajemniczą siła która bije każdego kto się znajdzie w owej strefie, zgodnie z tym ile w życiu nagrzeszył. Kilku tylko pieściło, innych porządnie pobiło, innych zmasakrowało. Te niewyjaśnione wydarzenia zaowocowały licznymi teoriami spiskowymi, większym popytem na usługi wszelkiej maści wróżek, licznymi nawróceniami i świetnym tematem dla prasy.
Głównym bohaterem i jednocześnie narratorem jest 45-letni, dość wykształcony Rosjanin, jeden z mieszkańców feralnego domu. Człowiek do bólu uczciwy, nieco zagubiony w ówczesnym społeczeństwie, nie omieszka nas poczęstować licznymi opisami niezbyt chlubnych zjawisk, jakie obserwuje w owym społeczeństwie.
Książka, choć być może bez bardzo wyszukanej fabuły, jest dość ciekawie napisana, miejscami zabawna, bardzo szybko się czyta. Pozycja jak najbardziej godna polecenia.
W przerwach od przygotowywania się do egzaminu z fizyki (a może odwrotnie? :)) gram sobie w DooMa II. Żeby było ciekawiej, gram na "High Violence" (najwyższy poza ździebko niegrywalnym nightmare ;p) i do tego bez mouselooka (tak jest ciekawiej). Ten poziom trudności ma to do siebie, że tak po 7 poziomach jest spory kłopot z amunicją. Pełno jest impów, demonów i co gorsza wszelkiego innego ustrojstwa które nie zostawia amunicji, a mało chaingunierów, a jeszcze mniej kolesi ze śrututówkami. Dlatego tak bardzo doceniłem zdolność dobrego operowania piłą. Jest to chyba najlepszy sposób oszczędzania amunicji (przede wszystkim od shotguna, który jednak jest najczęściej stosowaną przeze mnie bronią), zaraz po wykorzystywaniu agresji potworów (jako zagorzały pacyfista, jeśli mogę, lubię napuścić stwory na siebie, żeby sobie powalczyły między sobą ;p) i zaraz przed BFG9000 (o taak :)) i wyrzutnią rakiet, które jednak mają ten feler, że też wymagają amunicji. ;p
Co ciekawe, przy odrobinie wprawy można zdziałać naprawdę dużo zdziałać samą piłą. Nawet pomijając te najsłabsze potwory, które od razu się rozlatują. Gdy bawimy się z demonami (tymi różowymi i niewidzialnymi), a w około nie ma strzelców, zwykle można sobie poradzić samą piłą. Zwłaszcza przy jednoosobowym korytarzu (wówczas jest to właściwie kopanie leżącego), ale i na otwartych przestrzeniach można tak się zakręcić, żeby po kolei delikwentów wyrżnąć. Kłopot jest tylko jak cię przyprą do ściany, wtedy lepiej użyć BFG. :)
Jednakże zabijanie demonów piłą jest niezbyt wielkim wyzwaniem. Dużo ciekawiej wygląda walka z trochę silniejszymi przeciwnikami. Na ataki obłąkanego drwala są narażone przede wszystkim "głowy". Te czerwone z bazooką w gardle są chyba najłatwiejsze. Wystarczy się wbić. Problem się zaczyna gdy jest ich więcej, ale na szczęście dalsze etapy są bardzo przestronne i można je wybijać po kolei. Trochę cięższe są te co miotają małymi głowami, o których za chwilę. W tym przypadku trzeba dodatkowo zadbać o to, żeby nie zdążyła za dużo tych "łebków" naprodukować. Wbrew pozorom najbardziej upierdliwe są te małe łebki, bo tu nie wystarczy na chama wciskać "spust". Zwykle należy się uchylić i wbić się w potylicę. Biorąc pod uwagę, że pojawiają się one często hurtem, wolę już zmarnować trochę obrotówki, albo shotguna.
Co ciekawe piłą można nawet załatwić szkieletory (te wysokie z bazooką). W tym przypadku niemal konieczne jest zajście od tyłu lub od boku (chyba że się ma god mode), ale jak już się nauczysz czaić za rogiem będą twoje. Trzeba tylko uważać, bo czasami mogą uderzyć (nie wiem kiedy ale już udaje mi się temu zapobiegać) co jest trochę bolesne.
Jako ciekawostkę dodam, że da się też zaciukać piłą (parę razy mi się udało, ale jeszcze nie znam przepisu na sukces) te opasłe pokemony z z dwoma wyrzutniami rakiet zamiast dłoni i powtarzają coś na kształt "onimaru". tu oczywiście też trzeba się zaczaić, ale to niestety nie wystarcza. Boję się, że udawało mi się tylko dzięki jakiemuś ciekawemu bugowi.
W sumie taka gra w DooMa z ciągłym brakiem amunicji wymaga nie lada zdolności strategicznych. To spotkać dwie grupy potworów ze sobą. To się zaczaić, to ominąć. Bardzo fajna sprawa. :)
Nie mogę uwierzyć, że tak się rozpisałem i w końcu wyszedł tutoriial na temat oszczędzania amunicji w DooMie. Może następnym razem przejdę obie części samą piłą? :)
http://www.doomworld.com/classicdoom/info/music.php?wad=doom2.wad . Wspaniała sprawa. Trochę upierdliwy format, więc trzeba spędzić chwilkę na konwersję i otagowanie, ale myślę, że warto. :)
Jakiś czas temu zaprezentowałem mój pierwszy skrypt PHP, przygoda z tym językiem szybko się zakończyła. Przyszedł czas na perla – aż wstyd się przyznać, że dopiero teraz. Tak czy inaczej, po dość oględnym przestudiowaniu języka przyszedł czas na chrzest bojowy - napisanie skryptu, który generowałby menu na podstawie /usr/share/applications/. Być może jest już coś takiego, ale jak wszystkim dobrze wiadomo, jestem bardzo leniwy. Zadanie może nie wydające się być trudnym (choć pisanie w tego C to niezbyt kusząca perspektywa), aczkolwiek dobrze zweryfikowało to co zrozumiałem z kursu.
Zacznijmy od tego, jak ten skrypt działa. Mianowicie, parsuje on plik z szablonem (~/.fluxbox/menu.templ) i pliki *.desktop z /usr/share/applications/ i na podstawie informacji w nich zawartych buduje menu. Skrypt nie jest jeszcze doskonały i będzie wymagał dość radykalnego przerobienia, tak by elementy mogły być sortowane alfabetycznie i obsługiwały lokalizacje. Niemniej jednak działa i dość dobrze i szybko (w moim przypadku 0,03s) wypełnia swoje zadanie.
Pliki szablonowe mają bardzo prostą budowę – są to zwyczajne pliki menu fluxboksa, wzbogacone o wtrącenia w nawiasach ostrych (muszą być w oddzielnych linijkach), informujących program, jak interpretować /usr/share/applications/. Mój plik szablonu wygląda następująco i wyczerpuje opcje, które można póki co wtrącić:
<setterm urxvt -font -*-fixed-medium-r-*-*-20-*-*-*-*-*-*-2 -fg white -bg black>
<show-groups Network,Utility,AudioVideo,Game,Application,Office,Graphics,Science,System>
[begin] (Fluxbox)
[encoding] {UTF-8}
[exec] (uruchom) {fbrun}
<addterm terminal>
[exec] (WWW) {seamonkey}
[exec] (e-mail) {seamonkey --mail}
[exec] (vim) {gvim}
<insert-here>
[exec] (uaktualnij menu) {/home/bartek/fluxmenugen.pl}
[restart]
[exit]jak widać, nie jest tego dużo:
Na sam koniec natomiast gotowy skrypt, który udostępniam do dowlonego użytku.
#! /usr/bin/perl -w
$sdir = "/usr/share/applications";
$sext = ".desktop";
$favterm = "urxvt";
$destdir = $ENV{'HOME'}."/.fluxbox/";
open (TEMPLATE, $destdir."menu.templ") || die "Failed to open template file.";
if(open (DESTINATION, $destdir."menu"))
{
open (BACKUP, ">".$destdir."menu~");
while ( <DESTINATION> )
{
print BACKUP;
}
close (BACKUP);
}
close ( DESTINATION );
open (DESTINATION, ">".$destdir."menu");
opendir ( SHORTCUTS, $sdir ) || die ("failed to open $sdir.");
@shortcuts = grep { m/$sext$/ } readdir ( SHORTCUTS );
closedir ( SHORTCUTS );
%groups = ();
$ungrupped = "";
foreach $shortcut ( @shortcuts )
{
open ( SHORTCUT, $sdir."/".$shortcut);
while ( <SHORTCUT> )
{
if ( m/^Name=(.+)(\s*)$/ )
{
$name = $1;
}
elsif ( m/^Exec=(.+)(\s*)$/ )
{
$cmd = $1;
}
elsif ( m/^Terminal=(.+)(\s*)$/ )
{
$term = $1;
}
elsif ( m/^Categories=(.+)(\s*)$/ )
{
@cats = split ( /;/, $1 );
}
}
if ( !defined ( $name ) || !defined ( $cmd ) )
{
print "Failed to find essentional values for $shortcut\n";
}
else
{
if ( defined ( $term ) && $term eq "true" )
{
$cmd = $favterm." -e \"".$cmd."\"";
}
$stext = "[exec] ($name) {$cmd}\n";
if ( !defined ( @cats ) )
{
$ungrupped .= $stext;
}
else
{
foreach $cat ( @cats )
{
$groups{$cat} .= $stext;
}
}
}
}
while ( <TEMPLATE> )
{
if ( @tags = m/<(.+)>/g )
{
foreach $tag (@tags)
{
if ( $tag eq "insert-here" )
{
if ( defined ( @tagWhitelist ) )
{
foreach $group ( @tagWhitelist )
{
print DESTINATION "[submenu] ($group)\n";
print DESTINATION $groups{$group};
print DESTINATION "[end]\n"
}
}
else
{
foreach $group ( keys %groups )
{
print DESTINATION "[submenu] ($group)\n";
print DESTINATION $groups{$group};
print DESTINATION "[end]\n"
}
}
print DESTINATION $ungrupped;
}
elsif ( $tag =~ /^setterm (.+)/ )
{
$favterm = $1;
}
elsif ( $tag =~ /^addterm (.+)/ )
{
print DESTINATION "[exec] ($1) {$favterm}\n";
}
elsif ( $tag =~ /^show-groups (.+)$/ )
{
if ( defined ( @tagWhitelist ) )
{
push ( @tagWhitelist, split ( /,/, $1 ) );
}
else
{
@tagWhitelist = split ( /,/, $1 );
}
}
elsif ( $tag =~ /^show-all/ )
{
undef ( @tagWhitelist );
}
}
}
else
{
print DESTINATION;
}
}
Filmik mnie po prostu rozwalił. Zapewne, dla wielu nic nowego, bo filmik jest dość popularny na youtube, ale i tak zamieszczam: http://www.youtube.com/watch?v=U0kJHQpvgB8.