Cenzura internetu - krótkie przemyślenie

Mamy już kwiecień, Wielkanoc. Od styku stycznia i lutego minęły już ponad dwa miesiące. Czy ktoś pamięta jeszcze o bardzo głośnej w tamtym czasie sprawie z ACTA? Ktoś na pewno… Czy pamięta o tym większość opinii publicznej? Na pewno nie…

Wtedy wszyscy byli nakręceni, z akcją udało się trafić do naprawdę wielu osób, które pozornie nie były nią zainteresowane. Było to zresztą bardzo dobrze widać na ulicach – mało kto wiedział przeciwko czemu protestował.

W tamtym okresie udało się przeniknąć do mediów maintstreamowych, do szerokiej opinii publicznej. Stało się to za sprawą tak krytykowanych ataków „Anonymos” na witryny rządowe. Generalnie mówiąc: nie popieram takiej formy przekazu jak atakowanie strony, z którą chce się prowadzić dyskusje, ale uważam, że trzeba przyznać, że bez tych ataków, sprawa nigdy nie dostała by się do głównych mediów. Potrzeba było sensacji, złamania prawa, zrobienia czegoś „przeciwko systemowi”, aby zwrócić na tę sprawę uwagę tych środków przekazu. Dlatego też, uważam, że „Anonimowi” (zamierzenie lub nie) odwalili w tym aspekcie kawał dobrej roboty.

Temat ACTA już dawno ucichnął, pojawiły się nowe, które zajęły media. Rząd oficjalnie wycofał się z planów wprowadzania ACTA w Polsce. W związku z tym zniknęło też zainteresowanie większości społeczeństwa. Tymczasem, na horyzoncie pojawiły się doniesienia o pracach nad kolejną ustawą typu SOPA/ACTA/PIPA – tym razem jeszcze ostrzejszą.

Czy i tym razem uda się zapobiec cenzurze internetu? Już chyba jasne jest dla Was sedno mojego wywodu: aby było zainteresowanie opinii publicznej, musi być zainteresowanie mainstreamu. Tak więc czy teraz uda się przyciągnąć ich uwagę? Wątpię, żeby udało się tego dokonać kolejnymi atakami na witryny internetowe, w końcu już w styczniu było ich tyle, że ludzie powoli zaczęli przechodzić nad nimi do porządku dziennego…

Załóżmy jednak, że komuś uda się ściągnąć zainteresowanie na ten temat. Powiedzmy, że przejdzie do ataków realnych, obrzuca ministra Boniego kamieniami – taki personalny bruteforce ;) Czy ludzie będą się w stanie zmotywować do kolejnych protestów? Sądzę, że nie i widzę to już po moim mieście. W Olsztynie na pierwszą manifestację (25.01.12) przyszło około trzech tysięcy osób. Wynik nie najniższy patrząc na liczebność miasta i wyniki z reszty kraju. Na drugą manifestację odbywającą się bodajże trzeciego lutego przyszło już tylko kilkanaście.

Widać, że zdobycie zainteresowania ludzi i skupienie go na jednej kwestii przez długi czas jest praktycznie niemożliwe. W związku z tym, wybaczcie, ale happy endu nie będzie. Sądzę, że jeszcze maksymalnie trzy próby wprowadzenia tego typu prawa i któraś z nich na 100% zakończy się sukcesem.

I tak całkiem przy okazji: Wesołych świąt (nie wiem kiedy się składa życzenia, nie wiem kiedy są święta… jutro?). Jak nie trafiłem z terminem, to otwórzcie sobie we właściwym dniu :P

[SQL] Wordpress - pobieranie najdłuższych wpisów

Witam, dziś bez zbędnego gadania, będzie bardzo krótko.

Przedstawiam to proste zapytanie SQL, które pobierze tytuły wpisów i ilość słów w nich zawartych oraz posortuje po ich ilości.

SELECT
  post_title, 
  (LENGTH(post_content) - LENGTH(REPLACE(post_content, ' ', ''))) AS words
FROM 
  wp_posts
WHERE
  post_status = 'publish' AND post_type = 'post'
ORDER BY
  words DESC

Tak, to tyle. Na koniec screen z fragmentem wyniku działania na przykładzie mojego bloga:

Wynik zapytania

Amen, dobranoc państwu :)

Blackout - podliczanie punktów i CRON

W pierwszym wpisie o Blackoucie – silniku gier strategiczno-ekonomicznych via WWW przedstawiłem zaledwie szkic moich notatek. Dlatego też, zgodnie z obietnicą postaram się przybliżyć bardziej jeden z aspektów.

Ostatnio wziąłem na warsztat kwestię w xNovie dość kluczową, podliczanie punktów graczy. Podliczanie w xNovie punktów jest czynnością wykonywaną z panelu administracyjnego, która w założeniu raz dziennie ma policzyć punkty dla każdego gracza i sojuszu w grze, aby potem zapisać je w bazie i przedstawiać np. w zakładce „Statystyki”. Pierwszą sprawą jaka powinna zaintrygować każdego jest pytanie o to, dlaczego taka sprawa nie jest wykonywana automatycznie za pomocą CRON-a. Szczerze mówiąc nie wiem :D Wiem za to, że w xNovie cały skrypt odpowiedzialny za to jest wepchnięty jako zakładka panelu administracyjnego, dlatego nie za bardzo jest możliwość podpięcia tego do CRON-a. Trzeba by to wydłubać do osobnego pliku.

Dlatego też w Blackoucie podliczanie punktów służących do tworzenia statystyk zostało po prostu umieszczone w funkcji BuildStats() (konwencja nazewnictwa zgodna z resztą funkcji w xNovie, żeby nie robić bałaganu większego niż już jest). W tym momencie miejsce wywołania tej operacji (panel administracyjny/CRON) nie ma żadnego znaczenia. Całe podliczenie statystyk sprowadza się do wywołania jednej funkcji.

Budowanie statystyk zostało w xNovie rozbite na dwa pliki: admin/statbuilder.php i admin/statfunctions.php. Cztery funkcje znajdujące się w drugim pliku uprościłem lekko (bo standardowo, jak to w xNovie, generowały trochę nigdzie nie używanych danych) i jako, że są używane tylko przy podliczaniu punktów, przerzuciłem je do pliku z funkcją BuildStats()

Jeśli chodzi o objętość kodu. W xNovie: plik statbuilder.php – 308 linijek, statfunctions.php – 87. Razem daje to 395 linii kodu. U mnie plik spełniający funkcje dwóch powyższych, czyli BuildStats.php zajmuje 232 linijki.

Jedną z kilku przyczyn takiej różnicy w długości kodu jest to, co znalazłem na końcu statbuilder.php – otóż na koniec pliku do podliczania punktów doklejono na chama (nie zgadza się nawet poziom wcięć, choć to w xNovie norma) kod do usuwania nieaktywnych użytkowników. Najlepsze jest to, że w xNovie istnieje już funkcja do usuwania użytkownika razem ze wszystkimi potrzebnymi do tego rzeczami (usuwanie planet, flot, sojuszy itd. itd.)

Wprowadziłem też kilka usprawnień w tabeli która przechowuje statystyki graczy i sojuszów. Zacząłem przede wszystkim od skasowania zbędnych pól - ich liczba zmniejszyła się 25 z do 19, spadł więc też rozmiar trzymanych danych. Najlepszym dowodem na brak myślenia jest fakt, że data podliczenia statystyk, która jest jednakowa w całej tabeli jest przechowywana przy każdym jej rekordzie. A ich może być sporo - po jednym na każdego gracza i na każdy sojusz w grze.

Jeśli chodzi o drugą część wpisu, czyli CRON-a. W oryginalnej xNovie było wiele czynności, które można by wykonywać z jego pomocą - na czele oczywiście podliczanie punktów. Wstępnie w Blackoucie zdecydowałem się aby skrypt odpalany CRON-em realizował następujące zadania: podliczanie punktów, usuwanie graczy, którym minął czas na aktywację konta, w przyszłości także podliczanie rekordów (będą cache'owane i generowane raz na dobę) i wykonywanie innych cyklicznych czynności związanych z przewidywanymi nowymi możliwościami w grze. Oczywiście każda czynność wydzielona do funkcji, tak aby problemem nie było na przykład wywołanie jej z panelu admina.

I to na tyle w tym wpisie, siadam do kodu :)

Blackout - przedstawienie projektu

Już sporo czasu upłynęło od ostatniego wpisu na moim blogu, tak więc stwierdziłem, że nadszedł czas na podzielenie się częścią informacji o tym nad czym właśnie pracuję.

Być może pamiętacie poprzedni wpis  „recenzujący” skrypt xNova służący do tworzenia własnych klonów gry przeglądarkowej Ogame. Postanowiłem przepisać go po swojemu i uzyskać z niego w miarę uniwersalny silnik gier MMORPG via WWW. Zależy mi na tym, aby nie był ściśle ukierunkowany na grę dziejącą się w kosmosie, żeby po dokonaniu zmian w szablonach, plikach językowych i ewentualnie lekkich zmianach mechaniki móc na nim postawić dowolną inną grę strategiczno-ekonomiczną. Skrypt zdecydowałem się ochrzcić Blackout (nazwę, tak jak zazwyczaj wymyślił Rhino, chwała mu za to). Może nie jest to nazwa super oryginalna, ale bardzo chciałem uniknąć kolejnego potworka o nazwie "Super Game Uber-pro Elo Melo Maka-Faka Engine".

Jak wskazują daty modyfikacji niektórych plików – przepisywanie skryptów zacząłem dziesiątego lutego tego roku. Tak więc całkiem przypadkiem dziś mija miesiąc – sądzę, że to niezły pretekst do opisana tego co udało mi się zrobić i tego co mnie jeszcze czeka.

Tak więc: zacząłem od przygotowania najbardziej potrzebnych elementów do rozpoczęcia pisania. Poprawiona klasa baz danych, wzorowana lekko na tej użytej jeszcze w Iron CMS-ie, bardzo prosty logger błędów i króciutki system obsługi szablonów (nie ma chyba nawet 60 linijek).

Zacząłem rzecz jasna od napisania plików dołączanych do każdej strony – mamy więc znany z oryginalnej xNovy plik common.php – w przebudowanej formie, ale spełnia identyczne w założeniu zadanie – wykonuje czynności potrzebne przy wczytaniu każdej strony (np. sprawdzenie czy gracz nie jest zbanowany). W moim silniku pozostały jeszcze resztki ze sławetnego pliku todofleetcontrol.php (możecie o nim przeczytać w tym wpisie, punkt 10). Na razie okroiłem go tylko i przemianowałem na pure_evil.php – sądzę, że to bardziej adekwatna nazwa :D. Potem zostanie usunięty, a każda podstrona będzie ładować tylko to, czego faktycznie potrzebuje.

Jeśli chodzi o zakładki, które dla użytkownika są najważniejsze to:’

  • Podgląd – gotowy w 80%, nie gotowe opuszczanie kolonii i zmienianie nazwy planety
  • Budynki, laboratorium, stocznia, obrona – odtworzone działanie i wygląd z oryginalnej xNovy, mocna przebudowa planowana na następną wersję
  • Oficerowie – gotowe w 100%, jeśli nie liczyć części niedokończonych tłumaczeń
  • Handlarz – gotowy w 20%
  • Sojusz – na początku próbowałem wzorować się na oryginalnym alliance.php jednak po 4 godzinach stwierdziłem, że nie ma to żadnego sensu. Aktualna koncepcja jest rozrysowana na kartce i czeka na realizację
  • Flota – działa sama czynność wysyłania flot, w większości działa misja walki
  • Wiadomości – napisane całkowicie od nowa – jest tam kilka rzeczy do dorobienia i poprawki, ale ogólnie mówiąc plik jest prawie gotowy
  • Galaktyka – ciekawa historia: przerażony ilością zapytań jakie generuje ta zakładka (średnio 50 na odsłonę, przy 1 planecie w pokazywanym systemie) i ilością funkcji jakich używa tylko ta zakładka (17 plików – 1200 linijek) postanowiłem napisać go od zera. Zapytania w pętli zastąpione jednym podwójnym JOIN-em, wszystko ładnie umieszczone w jednym pliku – sądzę, że w wersji ostatecznej plik nie przekroczy 300 linijek
  • Imperium, Surowce, Technologia – gotowe
  • Rekordy – nawet nie zaczęte
  • Statystyki – prawdopodobnie działają, lecz to się okaże dopiero po zrobieniu skryptu do przeliczania punktów
  • Szukaj – gotowe
  • Zbanowani – gotowe, przebudowana tabela trzymająca bany, użyto relacji
  • Chat – gotowy, tylko trzeba go ujednolicić w jeden plik i ogarnąć system BBCode – jeden dla całej gry
  • Kontakt – działa
  • Opcje – mocno odchudzone, nie działa jeszcze urlop i usuwanie konta
  • Panel administracyjny – grubsza sprawa, temat na osobny wpis

Tak, wiem, w większości zrobiłem sobie z tego wpisu kolejne wcielenie notatek odnośnie skryptu, mam jednak nadzieję, że umieszczenie tego publicznie pomoże mi się zmotywować do dalszej pracy.

Jak widać, wiele jeszcze przede mną, myśląc o kilku plikach robi mi się słabo :D, ale jakoś to będzie… Więcej konkretów, mniej suchych notatek obiecuję już w przyszłym wpisie.

Przegląd skryptów genialnych #3 - xNova

Witajcie, w kontynuacji dawno zaczętej serii, w której przyglądam się największym „perełkom” pośród skryptów PHP. Dzisiaj pod nóż pójdzie coś specjalnego, prawdziwy as wśród asów. Drodzy Państwo, przywitajcie xNovę.

Najpierw krótko o samym skrypcie. xNova to skrypt, który ma umożliwić tworzenie gier MMO via WWW wyglądających dokładnie jak OGame (mówimy tutaj o starej wersji, bo od czasu wydania ocenianej wersji skryptu, OGame doczekał się całkowitej przebudowy interfejsu).

Ciężko jest nawet powiedzieć jaką wersję będę opisywał, bo xNova od wieków nie posiada oficjalnej strony/forum/bloga. Tak więc namnożyło się bez liku wersji (najczęściej po prostu przeróbek prywatnych osób, które połatały 3% bugów i zoptymalizowały kilka zapytań). Wersja którą mam, była opisana jako „xNova 0.3 Multilanguage”, ale zdefiniowana wewnątrz skryptu stała VERSION miała wartość 0.8, więc mamy niezły rozrzut.

W związku z ilością bugów oraz masą amatorsko tworzonych „nowych wersji” najczęstszymi poradami na bugi zamieszczonymi na „profesjonalnych suportach xNovy” nie są wcale poprawki błędnej linijki, tylko zdanie „podmień sobie plik z wersji 1.1A/5.5/x.x by Ktośtam” – to też bardzo skutecznie tworzy chaos w plikach.

No, ale przejdźmy do właściwej części wpisu:

  1. Już patrząc w strukturę katalogów możemy mieć pewne pojęcie o skrypcie. W katalogu głównym umieszczono foldery scripts i js. Oba zawierają skrypty JavaScripts, część z nich jest identyczna i po analizie można dojść do tego, że około 12 z plików nie jest nigdzie używanych.

  2. Wygląd skryptu opiera się na dwóch folderach: templates, w którym leżą pliki dla systemu szablonów i skins, w którym leżą obrazki i pliki CSS. Bardzo piękne założenie, szkoda tylko , że poza tymi folderami w katalogu głównym mamy jeszcze foldery css i images, więc zmiana szablonu nie daje możliwości pełnej modyfikacji wyglądu bez modyfikacji zawartości tych folderów. Ponadto wg mnie pliki JavaScript też powinny być zależne od wybranego theme’u, a więc leżeć w jego katalogu.

  3. Przejdźmy do instalacji. Uruchamiam folder z xNovą a tam bardzo prosty do zdiagnozowania błąd. Skrypt wymaga włączonej dyrektywy short_open_tag Wracamy po szybkim restarcie serwera :)

  4. Po zmianie konfiguracji próbuję jeszcze raz i co widzę? Błąd połączenia z bazą danych zamiast instalatora. W pliku index.php jest odpowiednia instrukcja, która przekierowuje do instalatora jeśli config.php jest pusty. Niestety, ktoś udostępniając tą paczkę ludziom nie pomyślał i zostawił swojego wypełnionego configa. Tak więc poprawmy jego błędy i wyczyśćmy plik config.php. Do trzech razy sztuka…

  5. Próbujemy jeszcze raz i oto naszym oczom ukazuje się przepiękny instalator… po francusku. Szkoda tylko, że silnik posiada możliwość zmiany języka w całej grze, w instalatorze także. Niestety nikt nie pomyślał nad możliwością wyboru języka instalacji.

  6. Lecąc na czuja wypełniamy tabelkę z danymi do DB, standardowy układ jak w każdym skrypcie. Ukazuje nam się podstrona z pociesznym napisem „La base de donnée a bien été installée!”. Szkoda tylko, że ktoś jej pożarł całego CSS-a.

  7. Styl powraca, tworzymy konto admina i mamy rejestrację z głowy. Czas się zalogować.

  8. Bez problemu loguję się do gry, a tam wszystko po… tak, zgadliście, po francusku. Instalator z automatu ustawia adminowi język na francuski. Trzeba go przestawić w opcjach konta/w bazie danych.

  9. Teraz, kiedy gra już działa, przyjrzyjmy się plikom: widać wyraźnie, że każda z podstron najpierw dołącza plik common.php, a więc to jemu przyjrzymy się na początku. Co my tam mamy? Widać, że istnieje możliwość ustawienia własnych ścieżek do kilku folderów oraz domyślnego języka gry. Tylko dlaczego to nie jest w configu? Potem widzimy dołączanie kilku plików, w tym todofleetcontrol.php.

  10. Ten plik jest na tyle wyjątkowy, że zdecydowałem się go pokazać w całości:

    <?php
    /**
    *
    *
    * @version 1
    * @copyright 2008 By Chlorel for XNova
    */
    
    // Fonctions deja 'au propre'
    include($ugamela_root_path . 'includes/functions/FlyingFleetHandler.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/MissionCaseAttack.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/MissionCaseStay.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/MissionCaseStayAlly.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/MissionCaseTransport.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/MissionCaseSpy.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/MissionCaseRecycling.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/MissionCaseDestruction.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/MissionCaseColonisation.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/MissionCaseExpedition.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/SendSimpleMessage.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/SpyTarget.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/RestoreFleetToPlanet.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/StoreGoodsToPlanet.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/CheckPlanetBuildingQueue.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/CheckPlanetUsedFields.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/CreateOneMoonRecord.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/CreateOnePlanetRecord.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/InsertJavaScriptChronoApplet.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/IsTechnologieAccessible.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GetBuildingTime.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GetRestPrice.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GetElementPrice.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GetBuildingPrice.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/IsElementBuyable.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/CheckCookies.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/ChekUser.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/InsertGalaxyScripts.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GalaxyCheckFunctions.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/ShowGalaxyRows.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GetPhalanxRange.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GetMissileRange.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GalaxyRowPos.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GalaxyRowPlanet.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GalaxyRowPlanetName.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GalaxyRowMoon.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GalaxyRowDebris.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GalaxyRowUser.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GalaxyRowava.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GalaxyRowAlly.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GalaxyRowActions.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/ShowGalaxySelector.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/ShowGalaxyMISelector.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/ShowGalaxyTitles.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GalaxyLegendPopup.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/ShowGalaxyFooter.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GetMaxConstructibleElements.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/GetElementRessources.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/ElementBuildListBox.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/ElementBuildListQueue.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/FleetBuildingPage.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/DefensesBuildingPage.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/ResearchBuildingPage.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/BatimentBuildingPage.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/CheckLabSettingsInQueue.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/InsertBuildListScript.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/AddBuildingToQueue.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/ShowBuildingQueue.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/HandleTechnologieBuild.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/BuildingSavePlanetRecord.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/BuildingSaveUserRecord.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/RemoveBuildingFromQueue.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/CancelBuildingFromQueue.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/SetNextQueueElementOnTop.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/ShowTopNavigationBar.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/SetSelectedPlanet.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/MessageForm.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/PlanetResourceUpdate.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/BuildFlyingFleetTable.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/SendNewPassword.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/HandleElementBuildingQueue.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/UpdatePlanetBatimentQueueList.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/IsOfficierAccessible.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/CheckInputStrings.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/MipCombatEngine.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/DeleteSelectedUser.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/SortUserPlanets.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/BuildFleetEventTable.'.$phpEx);
    include($ugamela_root_path . 'includes/functions/BuildRessourcePage.'.$phpEx);
    
    ?>
    

    Co my tu mamy? Bezmyślne dołączanie 78 plików za każdym wywołaniem strony. Nawet gdy się logujemy, rejestrujemy, oglądamy podstronę kontakt itd. silnik ładuje 78 plików potrzebnych tylko w grze.

  11. Kolejnym plikiem ładowanym w common.php jest plik /includes/db.php. On też jest w pewien sposób wyjątkowy: jedyne co robi to include’uje kolejny (jeden) plik. Gdzie tu logika?

  12. Wymieniony wyżej plik includes/db.php dołącza plik db/mysql.php. Jego zawartość też jest warta przytoczenia:

    <?
    function doquery($query, $table, $fetch = false){
    global $numqueries,$link,$debug,$ugamela_root_path;
    require($ugamela_root_path.'config.php');if(!$link)
    {$link = mysql_connect($dbsettings["server"], $dbsettings["user"],
    $dbsettings["pass"]) or
    $debug->error(mysql_error()."
    $query","SQL Error");
    
    mysql_select_db($dbsettings["name"]) or $debug->error(mysql_error()."
    $query","SQL Error");
    mysql_query("SET NAMES latin2");
    echo mysql_error();}
    
    $sql = str_replace("{{table}}", $dbsettings["prefix"].$table, $query);
    $sqlquery = mysql_query($sql) or
    $debug->error(mysql_error()."
    $sql
    ","SQL Error");
    
    unset($dbsettings);
    $numqueries++;
    $arr = debug_backtrace();
    $file = end(explode('/',$arr[1]['file']));
    $line = $arr[1]['line'];
    $debug->add("
    Query $numqueries:$query$file($line)$table$fetch
    
    ");
    
    if($fetch)
    {$sqlrow = mysql_fetch_array($sqlquery);
    return $sqlrow;
    }else{return $sqlquery;}}
    ?>
    

    Pierwszą rzeczą jaka rzuciła mi się w oczy poza genialnym układem kodu był fakt, że przy każdym zapytaniu jest dołączany config.php. No ktoś tam nie ma mózgu… nie można po prostu dołączyć go w common.php? Tak samo ewentualne łączenie powinno się odbywać nie funkcji wykonującej zapytania tylko tam.

  13. W folderze includes znajduje się plik databaseinfos.php, który na pierwszy rzut oka jest używany do tworzenia tabel przez instalator, a krótka analiza wykazuje, że używany jest tylko tam. W takim wypadku, czy nie logiczniej byłoby go usunąć automatycznie po zakończeniu instalacji (tak jak zresztą cały skrypt). Ponadto prościej byłoby chyba, gdyby znajdował się po prostu w folderze install.

  14. Samo nazewnictwo plików jest lekko mówiąc dziwne. Czy to mówiąc o sposobie zapisu (add_moon.php, ale już activeplanet.php), czy o języku (errors.php, paneladmina.php, verband.php). Do wyboru, do koloru!

  15. Jeśli chodzi o bazę danych, to widać jak na dłoni, że była dorabiana po kawałku zależnie od konieczności. Jednak nikt nie zadał sobie trudu, aby spojrzeć na nią całościowo, przeprojektować i choćby pousuwać zbędne pola z tabel czy ustawić bardziej optymalne typy dla pól. Jako najlepszy przykład można podać fakt, że informacje o występujących w grze Księżycach są trzymane w dwóch tabelach, przy czym jedna zawiera po prostu część danych z pierwszej tabeli. Niestety, aby to poprawić trzeba dokonać dość mocnej przeróbki skryptu, a mało kto ma tyle zawzięcia.

Powyższy skrypt jest bardzo wymownym przykładem na to jak nie powinno się tworzyć jakichkolwiek aplikacji. Zero organizacji pracy i początkowych założeń daje właśnie takie efekty. Można tylko współczuć ludziom którzy z wielkim zapałem chcą zrobić "super wypasionom grem na xNovie" nie zaglądając nawet do "jej wnętrza".

Facebook - maszynka do generowania contentu (zawartości)

Dzisiejszy artykuł chciałbym poświęcić stronie, która w pewnym obszarze zdominowała internet, a także życie realne niektórych osób. Mowa oczywiście o Facebooku - serwisie społecznościowym Marka Zuckerberga. Uściślając: skupię się na tym, na ile różnych sposobów Facebook zapewnia sobie generowanie ogromnych ilości treści (ang. content) przez każdego z użytkowników.

Kwestią podstawową jest oczywiście efekt kuli śnieżnej/wirusowego rozprzestrzeniania informacji czy jak tam kto jeszcze zechce go nazwać. Sprawa jest prosta, pokażę o co chodzi na najprostszym przykładzie. Osoba A właśnie polubiła stronę "Placki". Informacja o tym natychmiast pojawia się na jej tablicy, czyli sercu każdego profilu na Facebooku. Oprócz tego, że informacja o polubieniu witryny pojawiła się na jej tablicy, to informacja ta pojawia się w specjalnym boxie umieszczonym nad czatem, gdzie możemy prawie w czasie rzeczywistym śledzić wszystkie poczynania wszystkich naszych znajomych (dodanie kogoś do znajomych, polubienie komentarza/zdjęcia/strony, udostępnienie materiału, odpisanie na komentarz i tak dalej… Wszystko co tylko się da).

Jeszcze lepiej sprawa wygląda w przypadku udostępnienia jakiegoś materiału na swojej tablicy. Wiele stron na Facebooku jest zrobionych w następujący sposób. Intrygujący tytuł - np. "10 najładniejszych dziewczyn w Polsce". Aby obejrzeć treść strony musimy ją polubić oraz udostępnić ją na swojej tablicy.

Tak więc przy każdym użytkowniku mamy dwa zdarzenia: polubienie strony, a więc informacja nad chatem (i na tablicy lubiącego) oraz jej udostępnienie, które łączy się z pokazaniem informacji o tym nie tylko na tablicy udostępniającego, ale także w zakładce Aktualności każdego z jego znajomych. Oczywiście zachęca to tylko kolejne osoby do udostępnienia i polubienia danej strony. Jeśli któraś z nich to zrobi, to jednocześnie dowiaduje się o tym jej powiedzmy 100 znajomych. I mamy typowy efekt kuli śnieżnej.

Rzecz jasna zdarzenia udostępnienia strony możemy skomentować, a każdy z komentarzy (swój także) możemy polubić. Informacje o tym natychmiast pojawią się w tak zwanych powiadomieniach, które są bardzo łatwo dostępne z każdej podstrony Facebooka.

Powiadomienia to bardzo istotny element omawianej machiny. Domyślnie są one wyświetlane nie tylko na stronie, o części rzeczy jesteśmy informowani także emailami. Ponadto przy nowym powiadomieniu na stronie, dynamicznie zmienia się jej tytuł na pasku kart. Z "Facebook", na "(x) Facebook", gdzie x odpowiada liczbie nieprzeczytanych powiadomień. Wykorzystywane są praktycznie wszystkie drogi dotarcia z informacją do użytkownika. Dostępna jest też rzecz jasna opcja otrzymywania powiadomień poprzez SMS więc odpada problem braku włączonego komputera oraz aplikacji do obsługi FB na telefonie. Możemy też zasubskrybować powiadomienia z Facebooka jako zwyczajny kanał RSS.

Kolejnym sposobem na wygenerowania jeszcze większego ruchu a przy tym i treści jest to, że przy każdym odświeżeniu jakiejś podstrony Facebooka, w specjalnie wyznaczonym miejscu po prawej stronie mamy wybrane 5 stron, które lubią nasi znajomi. Po polubieniu którejś z nich natychmiast jest ona zastępowana kolejną propozycją strony do polubienia. Strony na Facebooku są zakładane dla: witryn internetowych, artystów, społeczności (np. popularna w ostatnich dniach "Nie dla ACTA w Polsce"), polityków, gwiazd, miast, miejsc i praktycznie wszystkiego co tylko możliwe. W związku z tym ich ilości nie trzeba nawet tłumaczyć, zawsze będzie nowa strona, którą akurat polubił któryś ze znajomych użytkownika, a więc jeśli choćby pięciu z jego znajomych też ją polubi, to informacja o tym dociera do wszystkich ich znajomych. Zakładając, że średnia liczba znajomych wynosi po około stu na osobę (a nie ma w tym żadnej przesady, przynajmniej nie w górę), to informacja o tym fakcie dociera od razu do pięciuset osób. Trzeba tutaj wziąć oczywiście poprawkę na wspólnych znajomych, tak więc ilość osób lekko się zmniejsza.

Następnym elementem tej machiny są aplikacje, które można tworzyć w obrębie Facebooka. Część z nich jest faktycznie przydatna, ale wiele to coś w stylu „wyślij czekoladkę Twojemu bliskiemu”. Całkowicie bez sensu, ale w tym momencie mamy od razu wpis na tablicy osoby A („A podarowała czekoladki B. Podaruj czekoladki komuś innemu!!!”) oraz na tablicy osoby B („B dostała czekoladki od A. Odwdzięcz się.” Właśnie w ten sposób działa duża część aplikacji, zachęta do jak najszerszego ich używania. Przy tej okazji można też wspomnieć o aplikacji, która co jakiś czas zamieszcza automatycznie na tablicy użytkownika wpis „XYZ is 0-100 percent happy Today”. Zero przydatności, no ale zawsze to można poszpanować czymś na tablicy. Naprawdę nie rozumiem po co ludzie tego używają.

To tylko część z aspektów budowy Facebooka, w celu uzyskania jak największego ruchu i jak najdłuższego zatrzymania użytkownika na stronie. O marketingu na Facebooku, który dość ściśle wiąże się z tym tematem (większy ruch == większy zysk) można by napisać naprawdę wiele książek, i z pewnością wiele ich jeszcze powstanie.

Jako ciekawostka: licząc powyższy artykuł, dorobiłem się już stu wpisów na sobak.pl :)

Przemyślenia o ACTA - akt pierwszy

Z powodu dzisiejszego niemyślenia w wyjątkowo silnej postaci, postanowiłem wybrać sobie (tak dla odmiany :D) temat mniej techniczny. Mianowicie, aby nie pozostać w tyle, stwierdziłem, że i Sobak będzie cool i napisze coś o ACTA.

Jaki jest mój stosunek do ACTA? Jakby to kogoś obchodziło, to jestem zdecydowanie przeciwny wprowadzaniu rozwiązań w tej formie, jeśli nie obchodzi to proszę wcisnąć ctrl+w i mieć święty spokój :) Przede wszystkim sądzę, że takie przepisy powinno wprowadzać się na szczeblu prawa krajowego czyli jako zwykłe nowelizacje istniejących ustaw. Wprowadzanie tego na poziomie umowy międzynarodowej momentalnie powoduje to, że każde z państw biorących udział przy tworzeniu i wprowadzaniu tej umowy będzie chciało zagarnąć część korzyści dla siebie. Z tego nie może wyjść nic dobrego.

Drugą sprawą jest sposób wprowadzenia ACTA. Informacja o tym wyciekła na 43 stronie komunikatu prasowego na temat rolnictwa i rybołówstwa. Jawna kpina ze wszystkich obywateli państw sygnujących umowę i tyle.

Następna sprawa jaką chciałem poruszyć to temat, zdaniem wielu, szczeniackich ataków na strony gov. Szczeniackie czy nie, uważam, że przyniosły w rezultacie bardzo dobry efekt. Stanowiły idealny materiał dla żądnych sensacji mediów mainstreamowych. Co dałoby kilkaset merytorycznych apeli? Nic, wszystkie przeszłyby bez echa. Sądzę, że kilka nawet tak prostackich akcji było konieczne aby zwrócić uwagę mediów, które kreują opinię większości społeczeństwa.

Sprawa któraś z kolei - "zawieszenie ratyfikacji" przez Premiera. Dlaczego w cudzysłowie? Ano dlatego, że nie ma z punktu prawnego czegoś takiego jak "zawieszenie ratyfikacji umowy międzynarodowej", więc po raz kolejny mamy do czynienia ze zwykłym zabiegiem który ma uspokoić wzburzone emocje. W końcu w Polsce odbyły się dziesiątki manifestacji ulicznych, w których łącznie wzięło udział kilkaset tys. ludzi.

Możliwości prawnego zablokowania ratyfikacji ACTA istnieją. Chodzi mi o ostatnio poruszany temat referendum ogólnokrajowego w tej sprawie. Cytując za artykułem 70 ustawy o referendum ogólnokrajowym, ustępem pierwszym:

O wyborze trybu wyrażenia zgody na ratyfikację umowy międzynarodowej w drodze referendum decyduje Sejm, uchwałą podjętą bezwzględną większością głosów w obecności co najmniej połowy ustawowej liczby posłów.

Czyli pierwszą przeszkodą jest konieczność uzyskania większości bezwzględnej w Sejmie, aby w ogóle móc zorganizować referendum w tej sprawie. Ponadto jeśli frekwencja referendum wyniesie poniżej 50%, to referendum nie ma głosu decydującego, a jedynie doradczy (wszyscy myślący wiedzą jak zostanie potraktowany taki głos). 50% frekwencji przy referendum to bardzo optymistyczne założenie. Skoro przy wyborach, które są niesamowicie mocno nagłaśniane gdzie tylko się da frekwencja jest niewiele wyższa, to łatwo nie będzie. Warto mieć na uwadze, że naprawdę duża część ludzi, która wyszła na ulice, to byli ludzie poniżej 18 roku życia, a oni w referendum brać udziału nie mogą. Trzeba by uświadomić ludziom, że ACTA nie dotyczy tylko internetu (a tak niestety myśli większość), że po jej wprowadzeniu nie mogliby dostać tańszych części zamiennych do samochodu czy tańszych zamienników przyjmowanych leków.

Podnoszony przez rząd argument, który mówił, że Polska podpisała ACTA, aby nie być postrzegana jako kraj popierający piractwo właśnie upadł ;) Niemcy właśnie wycofały się z zamiaru podpisania umowy. Jak widać są kraje, które dbają o własne interesy i wszyscy widzimy, że lepiej na tym wychodzą.

Jeśli chodzi o spotkanie Premiera z obiema stronami konfliktu ws. ACTA. Sam sposób jego organizacji był przygotowany tak, aby zjawiło się na nim jak najmniej chętnych. Zaproszenia na poniedziałkowe spotkanie zostało rozesłane w piątek, po godzinach pracy, świetne wyczucie. Przez to naprawdę wielu bloggerów i innych zaproszonych osób nie udało się na spotkanie (choćby Niebezpiecznik czy Kominek, a rząd zyskał genialny argument: podnosili tyle szumu w proteście, a nie chcieli przyjść porozmawiać na spokojnie. Bardzo zgrabne posunięcie :)

Cała sprawa ACTA, zdaje się przelała czarę goryczy u wielu ludzi napełniającą się już od dłuższego czasu. Mimo tego z perspektywy czasu (którą specjalnie chciałem mieć do dyspozycji podczas pisania tego wywodu) widać, że szum medialny powoli cichnie, zwłaszcza w mainstreamowych mediach, a cała sprawa pewnie skończy się na ratyfikacji umowy…

[PHP] Sprawdzanie poprawności numeru PESEL

Dzisiaj przedstawię prostą funkcję do walidacji numeru PESEL w PHP. Przyjmowany argument i zwracana wartość nie powinny być niespodzianką - bierzemy numer PESEL, a dostajemy wartość logiczną (prawda/fałsz).

Aby sprawdzić poprawność numeru PESEL, należy obliczyć jego tak zwaną cyfrę kontrolną. Jest to ostatnia cyfra numeru PESEL, obliczana na podstawie jego wcześniejszych cyfr i sprawdzana na podstawie wzoru (zakładamy, że a - j to kolejne cyfry PESEL-u licząc od lewej):

a+3b+7c+9d+e+3f+7g+9h+i+3j+k

Teraz należy obliczyć resztę dzielenia powyższej sumy przez 10. Jeżeli ostatnia cyfra otrzymanego wyniku jest równa 0, to numer jest poprawny. W przeciwnym przypadku cyfra kontrolna nie zgadza się z resztą. Przykładowa implementacja w PHP, może wyglądać następująco:

function peselValidate($pesel)
{
    $sum = 0;
    $weights = array(1, 3, 7, 9, 1, 3, 7, 9, 1, 3, 1); // Wagi dla kolejnych cyfr numeru PESEL
    
    foreach (str_split($pesel) as $position => $digit) {
        $sum += $digit * $weights[$position];
    }

    return substr($sum % 10, -1, 1) == 0;
}

Należy jednak zwrócić uwagę na dwie rzeczy:

  • poprawność cyfry kontrolnej nie gwarantuje, że dany numer PESEL istnieje - tylko tyle, że jest zgodny wymogami co do numeru. Faktyczne potwierdzenie istnienia danego numeru jest niemożliwe bez dostępu do ewidencji.
  • w Polsce odnotowano przypadki wydania nieprawidłowych numerów PESEL

Aktualizacja (21.02.2015): aktualizacja kodu funkcji, reorganizacja treści

Wikipedia - debile?

Szybka myśl, będzie krótko i na temat. Czy Wikipedia (Wikimedia Foundation) to aż tacy nieudacznicy, aby swoją szumnie zapowiadaną akcję zaciemniania Wikipedii w proteście przeciw SOPA tak nie dopracować? Prosta sprawa - ich zaciemnianie nie działa na Operze (testowane z kilku komputerów i lokalizacji na Operze 11.60).

Na innych przeglądarkach które testowałem jest ok (Fx, IE, Chrome nie posiadam…). Czy naprawdę takim problemem jest sprawdzenie  działania skryptu na wszystkich przeglądarkach? Przecież Opera to nie IE6, nie wymaga uber haxxorskich fixów.

Na stronie omawiającej protest Wikipedii pojawia się następujący tekst:

|Is it still possible to access Wikipedia in any way?

Yes. During the blackout, Wikipedia is accessible on mobile devices and smart phones. You can also view Wikipedia normally by disabling JavaScript in your browser, as explained on this Technical FAQ page. Our purpose here isn't to make it completely impossible for people to read Wikipedia, and it's okay for you to circumvent the blackout. We just want to make sure you see our message.

Cały myk polega na tym, że z desktopowej Opery żadna przeglądarka mobilna, a mój javascript jest na 100% włączony. Czyżby Wikimedia zechciała obdarzyć userów tej przeglądarki bonusową możliwością przeglądania ich witryn bez kombinowania? Szczerze wątpię… Jak zwykle rozbija się o lenistwo i brak profesjonalizmu…

Nowy interfejs YouTube

Witajcie. Można uznać, że nadszedł czas na nadrobienie zaległości. Dzisiejszy wpis chciałbym poświęcić nowemu interfejsowi YouTube. Został wprowadzony już ponad miesiąc temu, więc leniąc się z napisaniem tego wpisu miałem naprawdę sporo czasu na wyrobienie sobie opinii o nim.

Pierwszą sprawą jaka rzuca się w oczy, jest oczywiście strona główna, która moim zdaniem zaczęła bardziej przypominać Tablicę znaną z Facebooka niż to, co mieliśmy wcześniej na YouTubie. Duży nacisk położono nam na pokazanie treści pochodzących od zasubskrybowanych użytkowników, więcej jest też miejsca na „Wybrane dla Ciebie”. Aby nie marnować miejsca, część rzeczy pojawia się dynamicznie, po wybraniu odpowiedniej zakładki w menu po lewej.

Dla mnie bardzo dużym plusem jest pokazywanie na stronie głównej tego, czy mamy jakieś wiadomości do przeczytania. Wcześniej jeśli przeoczyło się powiadomienie na e-mail, to zostawało nam tylko okresowe sprawdzanie pewnej podstrony. Teraz fakt posiadania nowej wiadomości jest łatwiej zauważalny.

Moim zdaniem lekka zmiana kolorystyki też wyszła temu serwisowi na plus. Szare tło nie jest tak bardzo kontrastowe i jest przyjemniejsze dla oczu.

Bardzo wiele osób nie mogło przeżyć zmiany faviconki, ale ja odpowiem standardowo – kwestia przyzwyczajenia. Jak dla mnie nowa ikonka jest ok, i nie widzę żadnego powodu, aby czuć sentyment do poprzednich 256 pikseli…

Nie wiem, jak dawniej wyglądała podstrona np. umożliwiająca rozpoczęcie zarabiania na swoich filmikach, ale obecna prezentuje się bardzo jasno i przejrzyście.

Ładnie wyglądają też maile z cotygodniową listą filmików, które pojawiły się na subskrybowanych przez nas kanałach. A wyglądałyby jeszcze piękniej, gdyby były przysyłane z jednego adresu i mógłbym w Thunderbirdzie na sztywno ustawić im pozwolenie na wyświetlanie obrazków (korzystając z okazji: wie ktoś może, jak w Thunderbirdzie ustawić pozwolenie dla wyświetlania obrazków dla wszystkich maili z danej domeny?)

Niestety, prawie jak zawsze w takich wypadkach, sytuacja „pod maską” nie wygląda już tak dobrze. O ile 2524 błędy CSS są spowodowane głównie przez stosowanie prefixów przeglądarek w CSS3, których validator nie łyka, to 179 błędów w kodzie HTML spokojnie można by poprawić.

Sądzę, że był to bardzo udany lifting, a zmiany wyszły na plus. W moim subiektywnym odczuciu, nie ma niczego co zmieniłoby się na gorsze, albo moja czarna dziura wyssała mi to z pamięci.

Krótkie porównanie wprowadzonych zmian na przykładzie strony odtwarzania filmiku. Kliknij na zdjęcie, aby je powiększyć.

Stary player YouTube Nowy player YouTube