Béton brut

Trzy kolory: seledynowy

Bywacie czasem nieszczęśliwi? Co wtedy robicie? Pijecie? Palicie? Snujecie się po zaułkach? Programujecie?

Ja robię wszystko powyżej, naraz. W ramach nieustającej akcji „im więcej myślisz, tym bardziej nie chcesz” znalazłem się w momencie, gdzie potrzebowałem dnia ucieczki od zgiełku zwykłego dnia. Zamiast iść do biura poszedłem zwiedzać, a podczas zwiedzania wpadł mi do głowy pomysł na zajęcie umysłu. Na Twitterze jest sobie taki bot, który produkuje — zabawnie nazywane — palety kolorów. Nazywa się toto colorschemer.

Oto przykład:

schemer

Myślę sobie: a gdyby napisał bota, który potrafi wyekstrahować kolory z załączanych na Twitterze obrazków tym samym doprowadzając do SKYNET-u? Mógłbym generować z nich arkusze stylów z deklaracjami, palety do GIMP-a, czy to tam.

Brzmi jak marnowanie czasu!

Konsumujemy

Zanim zaczniemy naszą podróż po obrazku musimy zamienić plik znajdujący się na dysku w kupkę informacji. Dla Pythona dostępna jest biblioteka Pillow zawierająca w sobie wszystkie potrzebne funkcje. Użyjemy jej aby uzyskać piksele, kolory oraz rozmiar obrazka.

Na boku Bardziej zaawansowani czytelnicy mogą się skrzywić, że piszę funkcje zawierające tylko return — normalnie używam takich funkcji aby ułatwić sobie odpluskwianie i obsługę błędów. W tym przykładzie nie chcę dodatkowo zaciemniać, więc pozostawiłem tak, jak jest, no i funkcje mają bardziej zrozumiałe nazwy niż oryginalne metody.

def load_image(filename: str):
    return Image.open(filename)

def get_pixels(image: Image):
    return image.load()

def get_bounds(image: Image):
    return image.getbbox()

I tak, w kolejności: load_image wczytuje obrazek z dysku, get_pixels zwraca piksele na których możemy dokonywać analizy, get_bounds zwraca cztery wartości, które określają obszar zajmowany przez obraz.

Kolory na ekranie

Ekran komputera możemy reprezentować jako dwuwymiarową płaszczyznę której każdy punkt reprezentuje para wartości X i Y. X odpowiada za oś lewo-prawo, a Y, odpowiednia góra-dół. Pozycje zaczynamy liczyć od lewa w prawo i od góry w dół. To znaczy, że miara koordynat (0, 0) to piksel znajdujący się w górnym, lewym rogu.

Jeśli obraz ma rozdzielczość 1980x1080 to jego prawy dolny róg znajduje się na (1979, 1079) gdyż liczymy od zera.

Pod każdym z tych punktów kryje się święta trójca, Zielony, Czerwony i Niebieski, składowe kolorów w systemie RBG.

Kolory w RBG są reprezentowane przez bajt, który to bajt może przechowywać wartości numeryczne od 0 do 255. Czyli jeden piksel to trzy bajty informacji przybite do jakiejś pozycji na ekranie. Gdybyśmy chcieli sobie wyobrazić bardzo mały kwadrat, który ma bok składający się z dwóch pikseli, to moglibyśmy zapisać te dane w następujący sposób:

square = (
             (255, 0, 0), (0, 255, 0),
             (0, 0, 255), (128, 128, 128)
     )

Kolory RBG

Skoro wiemy w jaki sposób otrzymamy dane, zobaczmy, z czym nam przyjdzie pracować.

Pierwszy krok: w którą stronę ciąć

Przykładowy obrazków

Wszystkie obrazki zamieszczane na koncie przychodzą w dwóch formatach. Kolory są ułożone góra/dół lub lewo/prawo. Wykrycie typu obrazka będzie naszym pierwszym zadaniem. Utworzymy sobie typ wyliczeniowy (enum) żeby było nam łatwiej czytać kod.

Nazwałem mój enum Gravity, bo wydawało mi się, że to dobra, wiele mówiąca nazwa. „W którą stronę «spadają» kolory. Kiedy usiadłem do tego tekstu stało się oczywiste, że dużo lepszą nazwą byłoby Orientation. Udowodniłem tym samym teorię, że nazywanie rzeczy w programowaniu jest sztuką trudną.

class Gravity(Enum):
    VERTICAL = 0
    HORIZONTAL = 1

Zastanówmy się, jak wykryć, czy powinniśmy badać kolory idąc z góry w dół, czy też idąc z lewa w prawo.

Jeśli weźmiemy piksel znajdujący się pod koordynatami (0, 0), a potem weźmiemy piksel znajdujący się w przeciwległym rogu (0, szerokość obrazka) to jeśli są one takie same, znaczy, że układ obrazka jest góra/dół, bo cała pierwsza linia jest jednego koloru! Proste! W przeciwnym przypadku obrazek zorientowany jest lewo/prawo, gdyż wiemy, że kolor w lewym rogu jest inny niż ten w prawym.

Jak wykryć kierunek

Zrobimy z tego funkcję, która zwróci nam typ „grawitacji”.

def detect_gravity(pixels, bounds):
    max_width  = bounds[2]
    max_height = bounds[3]

    top_left_corner = pixels[0, 0]

    top_right_corner = pixels[0, max_width - 1]
    bottom_left_corner = pixels[0, max_height - 1]

    if top_left_corner == top_right_corner:
        return Gravity.HORIZONTAL
    return Gravity.VERTICAL

Wszystkie te kolory

OK, wiemy już jakiego typu obrazek wczytaliśmy. Teraz naszym zadaniem jest wybranie unikalnych kolorów. Zrobimy to idąc po linii i zapisując znalezione kolory. Powinno być całkiem prosto, wystarczy wybrać kierunek, zwiększać licznik o jeden i zapisywać do tablicy rezultatów unikalne wartości RGB.

Zerknijmy na kod.

def extract_distinct_colors(pixels, gravity, bounds):

    idx = 0

    if gravity == Gravity.VERTICAL:
        max_travel = bounds[3]
    else:
        max_travel  = bounds[2]

    distinct_colors = []

    while idx < max_travel:
        if gravity == Gravity.VERTICAL:
            pixel = pixels[0, idx]
        else:
            pixel = pixels[idx, 0]
        idx += 1
        if pixel not in distinct_colors:
            distinct_colors.append(pixel)
    return distinct_colors

Ustawiamy indeks idx na zero, ustawiamy rozmiar boku, którym będziemy podróżowali zależnie od «grawitacji», tworzymy pustą tablicę na rezultaty. Następnie kręcimy się aż do wyczerpania boku i sprawdzamy, czy właśnie odnaleziony piksel (dokładniej, trójca jego kolorów) jest już w distinct_colors, jeśli nie ma, dodajemy. Po zakończeniu operacji zwracamy zawartość tablicy.

Odpaliłem kod i wszystko działało, może nawet za dobrze, bo otrzymałem piętnaście kolorów, gdy spodziewałem się trzech. Dałem się nabrać swoim starym oczom, ale też udało mi się zapomnieć o faktach dotyczących obrazków w Internecie: kompresji. Jeśli popatrzymy na ofiarę naszej inspecji będziemy jasno widzieć (dosłownie) trudne do wyodrębnienia wahania w kolorze. Wahania, które ten naiwny kod, który szuka tylko unikalności, dokłada do listy. I dobrze robi, bo są to unikalne kolory, ale nie to chcieliśmy uzyskać.

Wiele kolorów w jednym pasku

Co teraz? Podglądanie obrazka pod lupą upewniło mnie, że te przekłamania w kolorze występują w niewielu miejscach, głównie tam, gdzie spotykają się dwa różne kolory. Rozsądnym sposobem byłoby liczenie ilości wystąpień. To pozwoli nam odrzucić sieroty po kompresji. Zmodyfikowałem więc kod w następujący sposób: dodałem occurance_counter, który zawiera liczniki wystąpień danego koloru. W bloku try…except sprawdzam w jakim miejscu w liście znajduje się obecnie odkryty kolor, a jeśli się nie znajduje (co podniesie wyjątek ValueError na metodzie .index()) znaczy, że widzimy go pierwszy raz. Tym razem z funkcji zwracamy dwie wartości: listę kolorów oraz ich liczniki.

def extract_distinct_colors(pixels, gravity, bounds):

    idx = 0

    if gravity == Gravity.VERTICAL:
        max_travel = bounds[3]
    else:
        max_travel  = bounds[2]

    distinct_colors = []
    occurance_counter = {}

    while idx < max_travel:
        if gravity == Gravity.VERTICAL:
            pixel = pixels[0, idx]
        else:
            pixel = pixels[idx, 0]
        idx += 1

        try:
            found_at_index = distinct_colors.index(pixel)
            occurance_counter[ found_at_index ] = occurance_counter[ found_at_index ] + 1
        except ValueError as e:
            distinct_colors.append(pixel)
            occurance_counter [ distinct_colors.index(pixel) ] = 1
    return (distinct_colors, occurance_counter)

Teraz muszę dodać tylko funkcję, która użyje obu tych informacji i zwróci mi n najczęściej występujących kolorów. Muszę przyznać, że byłem tu już trochę zmęczony, siedziałem na ławce w ciemnym parku, offline, paląc papierosy. Dlatego funkcja filter_top_entries nie jest może najbardziej przyjazna dla oczu początkujących, dlatego rozłożę ją może na czynniki pierwsze.

def filter_top_entries(count, distinct_colors, occurance_counter):
    filtered = sorted(occurance_counter.items(), key=lambda x: x[1], reverse=True)[0:count]
    return [distinct_colors[ x[0] ] for x in filtered]

Pierwszym paraemetrem jest liczba elementów, które chcemy uzyskać, dwa pozostałe to produkt extract_distinct_colors.

occurance_counter zawiera dane w następującym formacie:

    {
      '0': 12,
      '4': 1,
      '2': 34,
      []
    }

Indeksem w tym słowniku jest pozycja koloru w distinct_colors, a jego wartością jest liczba wystąpień. W Pythonie słownik posiada metodę .items(), która zwraca pary elementów, czyli gdybyśmy użyli jej na tym przykładowym kodzie, otrzymalibyśmy ( ('0', 12), ('4', 1), ('2', 34)). To właśnie przekazujemy do sortowania. Ale sorted() nie wie jak posortować dwuelementową listę. Dlatego też w parametrze key podajemy kawałek kodu, który wskaże jaki element z tej listy jest parametrem, który nalezy posortować. Pod indeksem 0 znajduje się pozycja koloru, pod indeksem 1 znajduje się liczba wystąpień. x: x[1] znaczy „do sortowania użyj ilości wystąpień, które znajdziesz w liście na pozycji pierwszej.

Ponieważ sorted() domyślnie sortuje od najmniejszej do największej musimy też poprosić o odwrócenie tego zachowania, gdyż szukamy najczęściej występujących kolorów. Do tego właśnie służy parametr reversed=True.

Produktem sorted() jest lista, więc możemy na niej użyć pythonowej składni do przycinania list, w tym wypadku [0:count] zwróci nam tylko fragment posortowanej listy do ilości podanej w pierwszym parametrze.

I to jest pierwsza linia. ;-)

Python posiada wygodną składnię do „kompresowania” wyrażeń normalnie zamykanych w for, to właśnie robi druga linia. Można ją przeczytać „dla każdego elementu w filtered, które uzyskaliśmy z sorted() weź element pod indeksem zero, który jest indeksem koloru na liście «unikalności» i zwróć to wszystko jako tablicę”

Alternatywnie możnaby to zapisać jako:

results = []
for x in filtered:
    results.append(distinct_colors[ x[0] ])

I już! Teraz powinniśmy mieć możliwość uzyskania trzech najważniejszych kolorów!

Składanie tego wszystkiego do kupy

Teraz możemy przetestować wszystko razem. Normalnie nie pisze się kodu testującego bezpośrednio w bibliotece, ale… wiecie, jak to jest. Zrobiłem sobie listę obrazków skradzionych z Twittera, wsadziłem je do listy i dla każdej z nich wywołałem wszystkie, dyskutowane wcześniej, funkcje.

Dopisałem jeszcze to_hex_expression, które zamienia RGB w znany nam dobrze format heksadecymalny używany w programach graficznych oraz CSS.

test_cases = [
    'test-cases/Dk82gZuVsAAcGho.jpg',
    'test-cases/Dk666IVUUAALxRx.jpg',
    'test-cases/Dk7kG4qU0AAJ5RL.jpg',
    'test-cases/Dk8oxdUVAAY6-JY.jpg',
    'test-cases/Dk9EPPVV4AA0obD.jpg',

]

from writers import to_hex_expression

for test in test_cases:
    print()
    image = load_image(test)

    bounds = get_bounds(image)
    pixels = get_pixels(image)

    gravity = detect_gravity(pixels, bounds)

    distinct_colors, occurance_counter = extract_distinct_colors(pixels, gravity, bounds)
    colors = filter_top_entries(3, distinct_colors, occurance_counter)
    for color in colors:
        print(to_hex_expression(color))

A oto rezultat:

test-cases/Dk82gZuVsAAcGho.jpg Gravity.VERTICAL
#446bae
#a10499
#35530b

test-cases/Dk666IVUUAALxRx.jpg Gravity.HORIZONTAL
#fcf779
#77ab56
#1fa874

test-cases/Dk7kG4qU0AAJ5RL.jpg Gravity.VERTICAL
#9eff00
#ff5c01
#cc406f

test-cases/Dk8oxdUVAAY6-JY.jpg Gravity.HORIZONTAL
#7f8f4e
#aca588
#ff6bb5

test-cases/Dk9EPPVV4AA0obD.jpg Gravity.VERTICAL
#24ff29
#1fb47a
#4a5d98

Trzy kolory „wyssane” z obrazka. Pełen sukces, dzień zmarnowany, wszyscy są szczęśliwi. Niestety, nie dotarłem do momentu w którym nauczyłbym kod łażenia „osobiście” na Twitter i podkradania obrazków, gdyż skończył się mi dzień.

Jeśli ktoś z czytelników uważa, że jest sens napisać drugą cześć, gdzie wpadlibyśmy grabić via API to można mi zostawić e-mail.

Przepraszam też jeśli ten tekst był zbyt chaotyczny i/lub bezużyteczny. Próbuję pobić prokrastynację przez brute force. Repozytorium z kodem jest dostepne na bitbucket, bronikowski/kaleidoscope.


Palec w oko

Homo erectus, homo sapiens, homo vatis1. Człowiek, co powstał z kolan, pomyślał po to, by opowiadać historie z dużego i małego „ha”. Człowiek z natury chce się wygadać, a czasem nawet chce być wysłuchany, ale głównie gadać.

Opowiadanie historii demokratyzowało się przez cały nasz czas na tej planecie. Od garstki liderów religii tłumaczących początek świata i bogów, aż po miliony użytkowników sieci społecznościowych z których wielu tłumaczy, jak świat się skończy i kto (zwykle „Oni”) się do tego przyczyni.

Gdzieś pomiędzy teraz a wtedy istniał świat w którym dostęp do technologii był ograniczony, ale ludzie nadal chcieli gadać. Był to świat w którym komputery osobiste były nadal zabawkami, a obliczeniowych mięśni dostarczały systemy UNIX-owe, popularne głównie w instytucjach naukowych, militarnych i uniwersytetach.

Każdy pracownik i student posiadał swoje konto, które było centrum cyfrowego życia. To tu przychodziły e-maile, tu kompilowało się oprogramowanie, tu odpalało aplikacje. Nic dziwnego, że katalogi użytkowników znajdowały się na partycji nazywanej tradycyjnie /home, był to prawdziwy dom dla e-bytów.

Ktoś w 1977 wpadł na pomysł protokołu, który pozwalałby „zapytać” systemu o fakty dotyczące danego użytkownika. Kiedy ostatnio był zalogowany, a jeśli jest, jak dawno dotknął klawiszy, jaki jest najnowszy e-mail czekający nań w skrzynce, kiedy ostatnio czytał pocztę, jak się nazywa i kilka innych, zbytecznych rzeczy.

Protokół ten został nazwany finger.

Informacje uzyskane tą drogą wydają się być trochę dziwne, ale jeśli weźmiemy pod uwagę, że „wsadzało się palec” w konto kolegi lub koleżanki z pracy/studiów, wiedza o tym, czy są przy terminalu i czy czytali już pocztę od czasu, gdy wysłaliście e-maila jest całkiem użyteczna.

Finger działał też w Internecie, gdy ten stał się faktem, człowiek mógł dla własnej frajdy dziabać paluchem znanych ludzi. No, znanych ludzi, którzy mieli konta na maszynach UNIX-owych, choć nie wiem, kto chciałby znać innych.

Co to ma jednak wspólnego z moim wstępem o potrzebie wygadania się? Finger czytał też dwa pliki z katalogu domowego użytkownika: .project i .plan.

W zamyśle miało to pomóc w organizacji pracy, gdzie .project opisywałby nasze długoterminowe działania, a .plan byłby zdaniem odpowiadającym na pytanie „co dziś robisz?”.

Niektórzy ludzie używali tych dwóch plików zgodnie z przeznaczeniem, związani obowiązkiem służbowym lub kompletnym brakiem poczucia humoru. Inni wsadzali do .planu tyrady o jedzeniu na stołówce, żarty, cytaty z książek, matematyczne dowody o wyższości Star Treka nad Star Wars i wszystko, co przyszło im do głowy.

Homo vatis1 nie zrodziło się wraz z erą Facebookiem, MySpace czy Twittera. Jeśli dacie ludziom możliwość napisania zdania, to znajdą się natychmiast ludzie piszący zdania ważne, zabawne i irytujące. Oraz ich czytelnicy.

W latach dziewięćdziesiątych finger został uznany przez większość administratorów za daemon niebezpieczny: program uruchamiany zewnętrznie, przez Internet, który czyta prywatne pliki z katalogu domowego użytkownika, czasem z podwyższonym dostępem to źródło potencjalnego bólu głowy.

Jeden z pierwszych robali używających Internetu do rozprzestrzeniania się, Morris, używał dziury znajdującej się w implementacji protokołu.

Tym samym popularność .plan spadła niemal natychmiast do zera. Ludzie jednak nie przestali opowiadać historii, zmieniły się tylko platformy i media, od rylca do glinianych tablic po pióra wieczne, od .plan do mediów społecznościowych. Nikt nie zamknie nam ust póki jest miejsce gdzie można napisać zdanie, szalet miejski jest na to dowodem ostatecznym.

* * *

W Internecie ciężko znaleźć jakieś archiwa wpisów do .plan, jego natura była bardzo efemeryczna. Jedyne popularne archiwum to .plan Johna Carmacka, autora wolf3d.exe i quake.exe.


  1. człowiek bard w kłamczo-łacinie 


Wolniej

Wiek średni to taki okres w życiu człowieka, gdy mimowolnie staje się „kołczem rozwoju osobistego” zaskarbiając sobie nienawiść wśród ludzi bliskich i przygodnych. Wszystkie błędy popełnione w życiu przepasuje czerwoną wstążką i obnosi je jak relikwie nie potrafiąc rozpoznać, że nie ma w nich nic wyjątkowego ani odkrywczego.

Uprawomocniony wchodzeniem w ostatni zakręt — już mocno przedłużonej — młodości, chciałbym Wam powiedzieć coś o uczeniu się. Jest to podwójnie skandaliczne, gdyż mury szkoły widziałem tylko od strony szarego tynku, gdy odbijałem odeń piłkę.

Struktura społeczeństwa zmieniła się już nie raz. Tak jak kiedyś chudy i spalony słońcem był z pewnością chłopem, którego jedynym dorobkiem jest garb tak bladaporcelanowa i pulchna była Hrabina. I gdy nawiniemy taśmę czasu w nasze okolice, sygnały statusu odwróciły się.

To samo stało się z „wolnym czasem”, choć w ogóle rzecz taka jak „wolny czas” w naszym rozumieniu jest produktem zupełnie nowym na rynku kultury. Kiedyś człowiek, co mógł się wyciągnąć na tapczanie i tak po prostu leżeć i wypierdywać dziury w materiale, był królem życia. Dziś kto nie uprawia wspinaczki i garncarstwa, najlepiej za jednym zamachem, jest prostakiem po stokroć. Wolny czas należy wypełnić zajęciami tak szczelnie żeby narastało w człowieku marzenie o rozwinięciu talentu do wypróżniania się w biegu, jak to czynią konie, między galopem od jednej aktywności do drugiej.

Są tylko dwie ważne rzeczy w uczeniu się nowych zdolności. Jak drogi jest sprzęt zakupiony do uprawiania hobby i jakiej klasy ludzie widzą Cię podczas go uprawiania. Kpię oczywiście.

Pierwszą rzeczą, o dziwno często pomijaną podczas skoku w nowe zajęcie, jest fakt, że trzeba te hobby na serio uprawiać. Mam pełen strój bramkarski, ale boisko widziałem pewnie 10 lat temu, nie wypada mi się nazywać „bramkarzem”, nawet „były bramkarz” brzmi głupio, jak „byłe dziecko”.

Jestem zwolennikiem pozytywistyczno-praktycznej definicji. Piszesz? Jesteś pisarzem. Nie piszesz? Nie jesteś. Biegasz? Jesteś biegaczem. Nie biegasz, nie jesteś. I może nie jesteś najszybszym biegaczem albo najbłyskotliwszym pisarzem. To jednak ocena wartości, a świat nosi wielu twórców, którzy są lepsi ode mnie, a nie naplułbym im na łeb, gdyby się palili. To wszystko są truizmy, ale bardzo łatwo się je zapomina, czasem nawet z premedytacją, gdy podczas wiosennego sprzątania przekładasz notatnik Moleskine z jedną zapisaną stroną (zakupy), buty do biegania i gitarę z zerwaną struną.

To prawda pierwsza: jeśli chcesz mieć jakąś przyjemność z uczenia się nowej rzeczy musisz ją uprawiać. Bardzo łatwo odstawiać teatr i grać przed sobą komedię. Ale nikt się nie śmieje, bo nikt tego nie ogląda.

Prawda druga: czym wolniej się uczysz tym większa szansa, że się nie poddasz.

W świecie zoptymalizowanym pod natychmiastową gratyfikację ciężko jest się przestawić na żmudną drogę. Jakby Jezusowi powiedzieć: „będziesz cierpiał, ale jaka to historia z tego wyjdzie”. Dlatego współczesnych synów bożych separuje się od zdrowego społeczeństwa w zakładach psychiatrycznych, komu by pasowała taka opcja!

Od miesięcy próbowałem nauczyć się Rusta. I moja droga zawsze przebiegała tak samo. Pobieżnie skonsumowany wstęp w dokumentacji. Kompilacja println!("Twoja stara");. Próba napisania czegoś. Frustracja. Porzucenie nauki na miesiące. GO TO 10.

Kilka dni temu postanowiłem, że przestanę skakać z jednego miejsca dokumentacji w drugie, próbując zmusić kompilator do respektowania mojego autorytetu wieloletniego programisty.

Godzina po godzinie, tworzyłem sobie katalog z nazwą jakiegoś elementu języka np. 03.array, 04.struct, 05.enum i mozolnie, pokornie, przepisywałem przykłady, modyfikowałem je, wymyślałem inne, testowałem hipotezy. Czasami aż mnie szczypało w dupę, że muszę znów pisać kod, który „wypisuje wszystkie elementy z tablicy wraz z ich indeksem”. I kiedy wreszcie zesztywniał mi kark okazało się, że podczas tych zupełnie głupich zajęć nie tylko załapałem idee, których opisy czytałem wcześniej na wyrywki, byłem też wewnętrznie zadowolony mimo że nie stworzyłem niczego oczywistego.

Teraz myślę do siebie, że „wolno” to może złe słowo, lepszym byłoby „metodycznie”, ale dychotomia „wolno” ↔ „szybko” brzmi mi lepiej niż „metodycznie” ↔ „chaotycznie”.

„Szybkość” to to, co marketingowcy umieszczają w dużym czerwonym kółku w nadziei, że odmieni Ci się to w głowie na „wygodę”. I w pewnym sensie jest to prawda. Ludzie spędzili wiele lat budując świat w którym 20% dostępnej wiedzy pozwala wykonać 80% zadań z zadowalającym skutkiem.

Dlatego dobicie do 21% spowoduje, że pobijesz większość. Dlaczego? Bo wolno.


Nazwa pliku jako UX

Ze wszystkich mądrych rzeczy, które powiedziałem i napisałem przez lata, tak o życiu, jak i o programowaniu, szczególne miejsce w moim sercu ma ta obserwacja:

Bardzo łatwo rozpoznać interface projektowany przez programistę: „godzina i piętnaście minut” jest wyrażone jako 1.25

Ta obserwacja była formą samokrytyki, gdyż podczas prowadzenia dema zauważyłem, że sam wykonałem takiego „międzymordziowego bazyliszka”. Od tego czasu, aż do teraz, oddałem wszystkie prace związane z tworzeniem interakcji ludziom, którzy się na tym znają. A przynajmniej powinni.

Zaszyłem się więc w ciemnej norze backendu, gdzie użytkownicy istnieją tylko jako miraże, tworzone i niszczone na potrzeby automatycznych testów. Bez historii, bez potrzeb, nie wysyłają świątecznych kartek. Perfekcyjna harmonia.

Ostatni projekt zmusił mnie jednak do opuszczenia mojej kryjówki, gdyż przypadła mi kluczowa rola, a że i projekt przypadł mi do gustu, byłem całkiem zadowolony i dałem nura.

Jednym z produktów systemu, który pisałem, były dokumenty do druku, gdyż część z naszych użytkowników jest cyfrowo wykluczona i nie chcemy aby potrzeba posiadania komputera z dostępem do Internetu była barierą. Ponieważ jedna osoba może mieć maksymalnie sto takich dokumentów, wymyśliłem i przeforsowałem zmianę. Dokumenty można scalać w pojedynczą grupę dokument, będący dla systemu równoważnikiem. Każdy dokument zawiera numer seryjny oraz sygnaturę kryptograficzną, dlatego zbudowanie takiej paczki jest całkiem proste i pozwala na łatwą weryfikację spójności.

Przepchnąłem ten pomysł zaczynając od współpracowników, przez kierownika projektu ze strony klienta, kończąc na akceptacji urzędu marszałkowskiego. Kiedy dostałem glejt z pieczęcią „no dobra, rób” usiadłem i zaprogramowałem.

Wszyscy żyli szczęśliwie kilka miesięcy, aż do momentu w którym Panie z rozliczeń zaczęły zwracać uwagę na rosnącą liczbę pomyłek przy zdawaniu paczek dokumentów. Bardzo dziwne, bardzo dziwne. Zalogowałem się jako użytkownik i poszedłem oglądać.

I wtedy zrozumiałem, że znów mam 1.25 jak w cytacie wyżej.

Dla własnej wygody trzymam paczkę jako SHA512 robiący za sumę kontrolną. To oczywiste, że tak robię. Kiedy piszę automatyczny test mogę od razu stwierdzić, czy dokument zapisany na dysku zgadza się z tym, czego się spodziewałem.

Dla mnie SHA512 jest oczywiste. Dla użytkownika natomiast otrzymanie pliku 4143aaf85e1a825463a8a202b9ee6ffa486[…]9a5edc944e3e473f89a889c85e093abe7adce5164dfefef0f3eded1e.pdf niesie bardzo niewiele informacji. W sytuacji, gdy mamy jedną paczkę problem rozwiązuje się naturalnie. Gdy użytkownik ma tych plików 12, heksadecymalny jazgot jest nie do przetrawienia.

Pracownik za kwadrans do fajrantu nie ma już mocy na sprawdzanie każdego dokumentu. A to rodzi błędy.

Dodałem więc nagłówek Content-Disposition: attachment; filename="%s_%s_%d" i sformatowałem nazwę pliku używając imienia, nazwiska i liczby dokumentów w paczce. Jan_Kowalski_15.pdf jest trudniej źle zinterpretować.

Od tego czasu liczba błędów spadła do zera.

Jedna linijka, a taka różnica. Nie wiem, czy być dumny z tej, szybkiej, reakcji czy też zawstydzony, że nadal mentalnie siedzę w backendowej jaskini.


Za kwadrans wiosna

Otworzyłem okno. Mimo ostrzeżeń o zanieczyszczeniu powietrza podjąłem decyzję, że lepszy jest dym płonących opon unoszący się z kominów łódzkich slumsów niż moja własna tytoniowa wędzarnia. Przez szparę wlał się chłód będący idealnym towarem zastępczym świeżości.

Usiadłem na fotelu i patrzyłem się tak w okno. Laptopa zostawiłem w biurze żeby się odtruć, widocznie nawyku patrzenia się w okna z tępym wyrazem na twarzy nie da się wyzbyć w jeden dzień odwyku. Kontemplowałem wszechświat, ale bardzo krótko, bojąc się że przez przypadek coś odkryję i będę musiał temu stawić czoło.

Zabrałem się za odpisywanie na listy i okłamywanie się, że nie jest mi zimno z powodu tego okna. Jak ludy prymitywne wierzyłem, że moje przekonanie o komforcie udzieli się, zwykle nie zważającym na byt ludzki, sferom niebieskim. I że będzie wiosna.

Po trzech godzinach, gdy wiosna się nie zjawiła, a w jej miejsce przyszła noc, musiałem uznać przewagę materii nad umysłem. Zamknąłem okno. Zapaliłem papierosa żeby nie dać się tej nowo nabytej świeżości zbyt łatwo.

I wtedy usłyszałem to leniwe, monotoniczne bzyczenie.

Tłusta mucha, pobudzona jak i ja, tą pierwszą obietnicą wiosny, podniosła swój zielony brzuch i zaczęła latać mi nad łbem.

Ja pisałem do paryżanki o chińskim atramencie, a ona przerywała mi co zdanie.

Zdałem sobie sprawę, że sam doprowadziłem do tej sytuacji. Nie przez otwieranie okna, nie. Widzicie, to wszystko przez technologię. 15 lat temu zwinąłbym w rulon gazetę i postawił się w roli sędziego, oskarżyciela i kata w jednej osobie. Po krótkiej gonitwie zgniótłbym ją na jakiejś płaszczyźnie i wydał z siebie pomruk zadowolenia; prymat homo sapiens zostałby zachowany.

Po upadku prasy papierowej mógłbym jej najwyżej przyjebać tabletem.

W sumie i tak nic na nim nie czytam.


Umówiłem się z nią na @833

Internet od zawsze był przestrzenią przyjazną eksperymentom i wynalazczości. I zgodnie z nazwą mojej ulubionej kolumny w „Młodym Techniku” — „Pomysły genialne, zwariowane i takie sobie”1 niektóre przetrwały nie tylko próbę czasu, ale stały się budulcem współczesnego świata. Inne wypadły z rąk twórców i z hukiem roztrzaskały się na betonowej posadzce rzeczywistości.

Pomysł, o którym chciałem Wam dziś opowiedzieć, tańczy na granicy tych trzech przymiotników. No, chyba, że będziemy patrzeć z punktu widzenia przyjęcia rozwiązania na rynku, wtedy nawet „takie sobie” to raczej laurka niż opis stanu faktycznego. Popatrzmy na niego oczami cyber-futurystów roku pańskiego 1998, kiedy Internet miał już pierwszy zarost.

Najważniejszym zadaniem sieci było połączyć nas wszystkich i stworzyć Globalną Wioskę, gdzie wektory wiedzy, różnorodności i zaradności dodadzą się rodząc sytuację, w której co drugi obywatel będzie Królem Filozofem. Dziś z perspektywy czasu widać, że idea wioski się spełniła: kumoterstwo, plotkarstwo i disko polo ma się dobrze.

Zostawmy jednak cynizm.

Kiedy zaczęliśmy pracować w globalnej wiosce okazało się, że wszyscy tyrają w systemie trójzmianowym. Idziesz do piekarza, a on śpi, gdyż jest na innym kontynencie, choć metaforycznie, na wyciągnięcie e-ręki. Strefy czasowe podstawiły nogę rozpędzającej się, globalnej, ekonomii. Próba umówienia się z kimś wymagała powtórki z geografii, ustalenia stref czasowych wszystkich uczestników, oraz tego, czy używają obecnie czasu letniego czy zimowego.

Swatch wpadł na pomysł jak rozwiązać ten nowy — na tę skalę — problem, sprzedając przy okazji niezłą górę zegarków. Swatch Internet Time!

Francja, po rewolucji, wprowadziła czas decymalny, oparty na 10 godzinach, które składały się z 100 minut po 100 sekund. Jako że ciężko się patentuje rozwiązania, które są jasno opisane w podręcznikach do historii, Swatch dokonał lekkiej modyfikacji: doba składała się z 1000 .beat, nie posiadały one strefy czasowej, więc były uniwersalne dla świata. Wystarczało, że umówisz się z nią na @833, weźmiesz od szefa akonto i wszyscy będą wiedzieć, kiedy to jest! Proste!

Oczywiście to nie zmieniło niczego w fakcie, że podróżujemy dookoła kuli plazmy i ludzie nadal śpią gdzieś kiedy zegarek Swatcha „wybija” @833.

Ja jednak byłem urzeczony pomysłem i choć nie miałem kontaktów z nikim, kto potrzebowałby się ze mną umówić w różnych strefach czasowych, dumnie włączyłem renderowanie ilości .beat na belce systemowej mojej Amigi. Próbowałem nawet nieśmiało podawać tak sformatowaną godzinę różnym znerdziałym znajomym, ale oni patrzyli tylko na mnie jak na dziwaka. Dwadzieścia lat później sytuacja nie uległa zmianie w tej kwestii.

Swatch nie był zadowolony z tego, że ich wynalazek jest tak beztrosko implementowany przez różnych obszarpańców, co pewnie nie mają zegarka ni garnituru i zrobił to, co każde lajfstajlowe korpo, zaczął ścigać „nielegalne dzielenie”, aż do momentu w którym nikt nie chciał się w to bawić. Trudno wymagać żeby każdy, z kim się umawiasz, miał zegarek tego samego producenta.

Dodatkowo Swatch, chcąc zapewne podbić wartość swojego wynalazku, wprowadził swoją własną strefę czasową, Biel/Switzerland, od której liczony był czas bazowy dla Internet Time.

Ktoś mógłby zapytać, czy jest jakaś merytoryczna różnica między umawianiem się na godzinę wg. UTC a tym oto wynalazkiem? Jest jedna, oczywista. Godzina z prefiksem @ jest bardziej e-cyber.

I tak pomysł genialny, bo stymulował fantazję o Jednym Świecie, zwariowany, bo ciężko wyobrazić sobie coś tak radykalnie dobrego żeby cały świat entuzjastycznie przytaknął, ale też taki sobie, bo w przeciwieństwie do innych zdobyczy epoki internetowej nie dane mu było oderwać się od cyca korpowładców.

A piszę o tym dlatego, że wracając wczoraj, lekko intelektualnie zmęczony imprezą, przypomniałem sobie o tym moim zegarku na belce Amigi i wymyśliłem, że dopiszę sobie to samo, tylko jako element belki tmuxa. Sama procedura jest trywialna.

  1. Weź obecną godzinę
  2. Policz ile sekund minęło od północy
  3. Ponieważ w 24h jest 86400 sekund, a chcemy 1000 jednostek, dzielimy to przez 86.4 i odrzucamy resztę
  4. Dzwoniący telefon to prawnicy szwajcarskich zegarmistrzów
  5. No division is illegal, hack the planet

Natychmiast po napisaniu kodu zdałem sobie sprawę, że jestem o godzinę za daleko. Jasne, muszę przekręcić datę na ich strefę czasową. Programowanie z uwzględnieniem stref czasowych przechodzi atrofię za każdym razem, gdy przestaję o nim myśleć. Poszedłem więc czytać dokumentację, ale za nic na świecie nie mogłem się dobrać do, nieoficjalnej przecież, strefy czasowej Swatcha.

Rzutem na taśmę odkryłem, że jest on równoważny UTC+1, dodałem więc brzydką arytmetykę na datach. Jestem pewien, że zrobiłem coś źle. Apple dwa lata wydawało iOS z błędem, który przestawiał budziki użytkownikom, a Microsoft miał firmware w Zune, które spowodowało, że jeden dzień nie dało się włączyć odtwarzacza. Skoro oni nie wiedzą, co robią, to ja też sobie pozwolę.

Efekt działania na terminalu:

#!/usr/bin/env python3
from datetime import datetime, timedelta
import pytz
import sys

def swatch_time(datetime_object = None, timezone_literal = 'Europe/Warsaw'):

    reset_clock = {
            'hour': 0,
            'minute': 0,
            'second': 0,
            'microsecond': 0
    }

    if not datetime_object:
        datetime_object = datetime.now()

    if not datetime_object.tzinfo:
        timezone = pytz.timezone(timezone_literal)
        datetime_object = timezone.localize(datetime_object)

    # Biel TZ is a unrecognized TZ that can be expressed as UTC+1
    # Thanks, Swatch
    swatch_timezone = pytz.timezone('UTC')
    datetime_object = datetime_object.astimezone(swatch_timezone) + timedelta(hours=1)

    midnight = datetime_object.replace(**reset_clock)
    time_delta = datetime_object - midnight

    if time_delta.seconds == 0:
        # don't divide against zero
        return 0

    return int(time_delta.seconds / 86.4)

if __name__ == "__main__":
    print("@{}".format(swatch_time()))
  1. Dział ten nazywałem też „Nygusem”, gdyż numery z lat 80-tych miały pana leżącego niedbale dookoła liter loga, standardowym zawołaniem bojowym w weekendy było „Babcia, poczytaj mi «Nygusa»”.

Opóźniona gratyfikacja

Ze wszystkich rzeczy, które najbardziej oczarowały mnie w tym całym komputerowym bajzlu, musiałbym wymienić automatyzację na pierwszym miejscu.

Mimo płynących lat nadal odnajduję okruchy magii w tym, że komputer, raz nauczony, potrafi powtarzać rzeczy bez czujnego oka operatora. Kiedy otrzymałem swoje pierwsze konto z dostępem do powłoki, napisałem na szybko dwa skrypty, które wysyłały e-maile na specjalny adres, przesyłający informację dalej na telefon komórkowy via SMS. Pierwszy informował mnie o loginach na mój shell. Siadałem do terminala, logowałem się i… pik! Drugi śledził mój /var/spool/mail/opi i przysyłał mi każdego ranka informację o ilości e-maili. Serce aż bije mocniej, gdy wspomnę tę ekscytację czymś, co dziś brzmi jak błahostka. Zabawne, że dziś moje skrypty działają odwrotnie i ukrywają pocztę, która do mnie przyszła. Odwrotność miłości to nie nienawiść — to obojętność.

Zanim otrzymałem to konto cierpliwie wertowałem „książkę do nauki Linuksa”, jedną z tych książek, które leniwie tłumaczą to, co i tak jest dostępne na stronach podręcznika man, ale to było jak uczenie się języka przez zapamiętywanie słówek, bez wymowy, bez kontekstu, ale z pełnym nabożeństwem iluzji zdobywania wiedzy.

Tam też natknąłem się na atd, daemon wykonujący polecenie — bądź serie poleceń — opóźnione o zadany czas. Prawie zemdlałem. Idea, że jest komputer, który nie tylko jest non-stop włączony, ale także non-stop „w Internecie”, a do tego mogę mu powiedzieć, co zrobić za kilka godzin wydawała mi się jak odkrycie podróży międzyplanetarnych przy użyciu puszki mielonki, kawałka sznurka i bardzo silnego postanowienia woli: niesamowite, a w ogóle nieprawdopodobnie, że ludzie nie siedzą godzinami wymyślając, co komputer może zrobić za godzinę! To musi zmienić cały świat.

Nie zmieniło świata, a wraz z upływającym czasem ludzie w ogóle przestali wiedzieć o atd. Kiedy zainstalowałem Debiana na nowym laptopie atd nie było w standardowym zestawie pakietów. Jak wtedy, gdy Twoja matka komunikuje Ci na obiedzie, że znalazła twoje stare magazyny i wyrzuciła je do śmieci. Maska dorosłości przykrywająca doskonale uczucie żalu.

Mimo to, myślę sobie, at jest jedną z tych rzeczy, która spadła za ladę i może znajdzie się jak będziecie malować, w przyszłości. Nie wiem, jak ludzie żyją bez tego, ale może to tylko ja. Może po prostu nikt nie powiedział ludziom, że mają non-stop takie nisko-profilowe cudeńko w systemie? Może jeśli im powiem, na ten przykład w notce, trochę wstawiony, to odnajdziemy wspólny język.

at to komenda, która jest klientem daemona atd, pozwalająca na uruchomienie polecenia, lub serii poleceń. W odróżnieniu od Crontaba zadania te są jednokrotnego użytku. Można oczywiście wywoływać skrypty.

Przykładowo, mój skrypt odpowiedzialny za deploy nowej wersji oprogramowania ma linijkę:

echo "./skrypt.sh" | at 1:00

Znaczy to ni mniej, ni więcej że o pierwszej w nocy, kiedy użytkownicy już zasną, pojęte zostaną działania integracyjne, które teraz powodowałyby ból zębów użytkowników. Gdybym używał do tego Crona lub innego cyklicznego odpalacza musiałbym przekazać w jakiś sposób stan, stworzyć pusty plik albo odłożyć wartość do redisa, to tylko komplikuje rzeczy.

Kiedy wychodzę z domu, a pasek „podstępu” pobierania tego czy owego waha się non-stop pomiędzy 30 a 40 minutami piszę:

sudo at now+1 hour, podaję hasło i w linii poleceń at piszę poweroff. Za godzinę komputer złoży się bez mojej interwencji i nie będzie marnował prądu.

Mieliście kiedyś do wykonania zadanie na serwerze, który jest pod sporym obciążeniem, które to obciążenie powoduje, że zadanie wykonywałoby się zdecydowanie zbyt długo lub — co gorsza — spowodowało śmierć ważnych części systemu przez wysycenie I/O? W skład at wchodzi polecenie batch, które nie czeka na dopełnienie się konkretnej daty, odpala zadane kiedy load spadnie do 1.5; jeśli wydaje się Wam to bezużyteczne nigdy nie widzieliście aplikacji, która rozpędzona łyka zasoby jak odkurzacz-fetyszysta.

Kolejkę oczekujących zadań obsługujemy przy pomocy atq, które wyświetla listę wraz z unikalnym identyfikatorem, którego możemy użyć wraz z atrm celem usunięcia.

Tak wiele, tak niewiele.

I wiem, że jest pewnie lepszy, współcześniejszy, daemon. Wysyła powiadomienia na Slacka, całuje użytkownika w czółko i w ogóle. Ale! Te narzędzia nie przeżyły tyle lat jako część *NIX-a dlatego, że panowie z workami, na których widnieje symbol dolara, sypali mamoną aż do momentu w którym krytykanci się poddali i odlecieli prywatnymi odrzutowcami. To po prostu jednofunkcyjne narzędzie, które robi, co powinno.

KISS your atd.


Rozszczepienie

Zanim Reddit stał się pierwszą stroną Internetu, był trzecią. Nie istniał jeszcze ekosystem pozwalający zwykłym użytkownikom na relatywnie tani dostęp do zawszedostępnego składu informacji, a serwisy hostujące obrazki dzieliły się na trzy rodzaje.

Ofertę darmową, obsraną wyskakującymi okienkami, obwieszoną reklamami, pod których ciężarem usługa czołgała się, irytując użytkowników. Ofertę płatną, obłożoną ograniczenami transferów i relatywnie kosztowną, często powiązaną z życiem profesjonalnym lub prywatnym, które może nie każdy chciał wiązać ze swoimi postami na Reddicie, gdzie tematem przewodnim jest dmuchanie kreskówkowych postaci, dosłownie. Istniały wreszcie serwisy chałupnicze, które studenci budowali w ramach podpieprzania zasobów serwera .edu.pl. Serwisy te często zapewniały szybkość i wygodę, a także pewność, że znikną one prędzej czy później bez słowa wyjaśnienia, grzebiąc twoje bardzo zabawne zdjęcia i łamiąc nieskończoną ilość odnośników ućkanych po forach.

Nie było dobrze, zwłaszcza w świecie, w którym obrazki — na serwisach takich jak Reddit, będących bezpośrednią ewolucją imageboardów — są największym dobrem.

Ktoś rzucił kiedyś pomysł, żebyśmy sfinansowali jeden z serwisów, który został demokratycznie wybranym docelowym miejscem do wieszania obrazków, bo prawdopodobieństwo podzielenia przez niego losu innych „dobrych serwisów powstałych z potrzeby społeczności bez pieniędzy” zaczęło oscylować dookoła jedynki.

Ludzie rzucili jakieś dolary i orkiestra grała dalej. O tym, że też rzuciłem, dowiedziałem się po latach z e-maila z podziękowaniami. Jestem tak szczodry, że nawet się nie chwalę i nie pamiętam, czyj serwis ratuję przed zgonem. Skromnie.

Minęły lata. Życie z datków, reklam i „sponsorowanych obrazków” było ciężkim chlebem.

W przemyśle podwykonawczym nie ma miłości. Nikt nie kocha gościa obierającego ziemniaki na zapleczu czy pilnującego, żeby mieszadło mieszało z dobrą szybością. Reddit używał serwisu Imgur tak, jak się używa podwykonawcy: z obojętnością, kiedy wszystko idzie dobrze, z nienawiścią, jeśli coś nie działa.

Nie widząc innej szansy na przetrwanie, Imgur postanowił zbudować własną społeczność, umożliwiając komentowanie i gromadzenie się pod różnymi banderami — sprawdzony przepis na zwabienie ludzi. Był dużo mniej przerażający niż Reddit (nie widzę młodych ludzi, którzy zacierają ręce, myśląc „Ojej, spartański design, gdzie w wątku o meczu są tysiące — wątkowanych! — komentarzy i osiem lat kultury opartej na sraniu we własne gniazdo! Dołączam!”). Użytkownicy wsiąkali więc na tyle szybko, że pojawili się nawet kapitaliści wysokiego ryzyka (cudzego) z workiem pełnym twardej waluty.

Większość użytkowników Reddita nadal używa Imgur jako miejsca zrzutu obrazków.

Uf, to historia, której mogłem nie pisać, ale mam pół litra zielonej herbaty do wypicia.

Użytkownicy Reddita wrzucają obrazki na Imgur bezwiednie, często anonimowo, półautomatycznie lub nawet automatycznie. Wszyscy nadal myślą o nim w kontekście serwisu usługowego. Gdy czasem kliknę jakąś galerię (praktycznie jedyny przypadek, kiedy ląduję na stronie ich serwisu bezpośrednio), widzę to, co widzi ich społeczność. I tu ostatnio zadumałem się.

Mamy sytuację, gdy jedna strona traktuje drugą przedmiotowo, ale ta druga, bez wiedzy pierwszej, rozwinęła własną kulturę i społeczność. Wszystkie obrazki trafiają więc do mieszkańców serwisu obrazkowego bez jakiegokolwiek kontekstu, a sam wrzucający nie ma najmniejszego powodu, żeby podejmować interakcję z elementem lokalnym.

Serwisy się widzą

Nie uderzyłoby mnie to, gdybym któregoś dnia nie nadganiał galerii subreddita /r/fountainpens — który, jak nazwa wskazuje, służy do chwalenia się piórami lub charakterem pisma („those who can’t, buy”) — i nie poczytał załączonych komentarzy. Ludzie pisali jakieś bzdety, bzdety, jakich nikt zainteresowany tym hobby by nie pisał. Popatrzyłem jeszcze, sytuacja się powtarzała.

Wyobraź sobie, że żyjesz gdzieś, gdzie jest nowocześnie i młodzieżowo. Co jakiś czas twój dom najeżdzają barbarzyńcy i wieszają na ścianach barokowe obrazy podpisane łaciną. Nigdy nie mówią nic, nie usprawiedliwiają się i nie tłumaczą. Wieszają i wychodzą. Żyjecie w dwóch przenikających się wszechświatach, obserwujecie to samo, widząc zupełnie coś innego. Nie w materialnym sensie, bo piksele są te same, ale cały sens pojawiający się wraz z odpowiednio umocowanym punktem widzenia jest inny.

Ten tekst nie zawiera żadnej puenty, gdyż do niczego Was nie przekonuję. To tylko jedna z tych obserwacji, od których robię „huh…”. Kiedyś bym ją zamienił w zbyt długą notkę o niczym.

Punkt widzenia zależy od zalogowania się.


Tay, otwórz drzwi

Technologia nie zwalnia. Przeszliśmy od komputerów, których nie można podnieść, przez komputery, które można, następnie takie, które można rzucić, aby zakończyć na tych, które upuszczamy niechący. Wielkimi krokami nadchodzi era osobistych asystentów w ogóle odpiętych od idei „urządzenia, które się posiada”, takich jak Amazon Echo czy Google Assistant.

Sukces jest jednak daleko, bo mimo olbrzymich skoków, nadal technologie Udające Inteligencję podczas interakcji bardziej przypominają grę w 20 pytań niż dramatyczny dialog z HAL-em 9000 o zamykaniu drzwi. Wielkie firmy już dawno zauważyły, że ciężko jest zbudować taką technologię bez dobrego źrodła informacji. Jeśli algorytmy mogą być „uprzedzone” uprzedzeniami autorów, to co dopiero dane, które są dużo mniej rygorystyczne w swej naturze. Czasem myślę, że Douglas Adams stworzył Marvina, robota z depresją, jako ostrzeżenie przed uczeniem algorytmów sztucznej inteligencji na korpo-poczcie i zgłoszeniach błędów, których z pewnością międzygalaktyczny rząd miał pod dostatkiem.

Najtańszą siłą roboczą na rynku są obecnie użytkownicy. Nie tylko robią rzeczy za darmo (ewentualnie za „odznaki”, które można spieniężyć), ale reprezentują w miarę szeroką gamę opinii, pochodzą z różnych kultur, rozmawiają różnymi językami. Nie ma takiej akcji świadomościowej, która mogłaby wtłoczyć w firmy technologiczne równie zróżnicowany wycinek świata.

Użytkownik skataloguje obrazki, użytkownik zabawi parser lingwistyczny rozmowami o życiu, użytkownik otaguje i utworzy listy. Użytkownik nie ma związków zawodowych, nie ma też wolnego.

W świecie synergii biznesowej firmy udostępniają swoich użytkowników innym firmom tak jak pożyczasz sąsiadowi młotek czy szklankę cukru — normalne zachowanie pozwalające budować partnerstwo i wzajemne zaufanie.

Tak właśnie Microsoft wpadł na pomysł, żeby zapędzić użytkowników serwisu Twitter — który to serwis służy do niszczenia wyobrażeń o aktorach i politykach oraz jako efektywny transmiter krótkich utarczek słownych — do „pracy przez zabawę”, tj. rozmawiania z ich botem, którego przebrano za nastolatkę i nadano odpowiednie imię: Tay. Taka forma międzymordzia (pomiędzy algorytmem danych rozgryzającym zdania na części mowy celem łatwiejszego połknięcia a białym pudełkiem, w które wpisuje się wypowiedzi) miała zmiejszyć napięcia zawsze budujące się w interakcji między człowiekiem a maszyną. Oraz zawęzić grupę biorącą udział w pracy przy pomocy naturalnego filtru społecznego („kto rozmawia z nastolatkami na Twitterze?”).

Microsoft, firma przechodząca drugą młodość, po pozbyciu się starych ludzi zyskała wigor, ale straciła też wiedzę zdobytą przez lata: pytanie Internetu to rosyjska ruletka w wersji „ciężko”, pięć kul i jedna wolna komora.

Tay zaczęła jako pogodna nastolatka z ograniczonym zasobem zainteresowań i ubogim słownikiem. Blogi technologiczne, widząc opcję na odfajkowanie jeszcze jednego wpisu, przepisały notkę prasową, co zamieniło się znów w zainteresowanie. Twitter gadał do Tay, ona słuchała.

Wiadomości dosięgnęły wreszcie podbrzusza Internetu, o którym z wypiekami na twarzy korporobotnicy czytają na smartfonach w kolejce do okienka. Tajemne, mroczne, skandaliczne, bezwzględne, składające się głównie z innych znudzonych korporobotników za siedmioma serwerami proxy.

Następnego dnia Microsoft zamknął projekt. Tay, przyuczona przez element anarchistyczny, stała się grubiańska, głosiła niepopularne tezy podszyte ksenofobią i rasizmem. W jeden dzień z cichej nastolatki na Twitterze wykluł się potwór, rasista, cynik, automaton powtarzający głupoty za swoimi rówieśnikami, a przecież spuszczony z oczu tylko na chwilę przez rodziców, którzy mieli dobre intencje.

Najbardziej boli mnie, że ludzie, zamiast gratulować Microsoftowi, wieszali na nim psy. Nikt nigdy wcześniej nie dokonał tak kompletnej, dokładnej symulacji bycia nastolatkiem. Ktoś powinien dać im nagrodę. To absolutny przełom.

Być może następnym produktem będzie para botów. Na start każdy z nich będzie przekonany 100% o swojej racji i niech skalibrują się wzajemnie. Najlepiej na Fecebooku1.

  1. Kaja zgłosiła jako literówkę, ale zostawiam, gdyż piękne.

Lista Osobista: podkasty, część trzecia

Listy z rzeczami do klikania cieszą się niezmiennie popularnością w Internecie. Nie wymagają wielkiego poświęcenia ze strony autora, są bezbolesne dla czytelnika. Cała filozofia zamyka się w wymienianiu rzeczy, czasem w kolejności, która ma wykazać „dobrość” lub „słabość” tematu listy, czasem bez tego rodzaju zobowiązań.

Nie chcąc kompletnie stracić rynku list internetowych, przedstawiam Wam trzecią edycję podcastowej listy przebojów wprost z mojego odtwarzacza. Napisałem już tyle wariacji tej listy — prywatnie, e-mailem, na życzenie — że w przyszłości skrócę sobie pracę i będę mógł wysłać tylko odnośnik.

Rozrywka, kultura i sztuka w słuchawki stuka

Kultura

99% Invisible

http://99percentinvisible.org/

Otwieram podcastem, który jest pierwszy na tej liście tylko dlatego, że taka jest natura sortowania w mojej aplikacji do grania. I nie, to nie jest zły podcast, to jest bardzo dobry podcast. Tak dobry, że często przeskakuję odcinki (wydawane w cyklu tygodniowym).

Brzmi bez sensu? 99% Invisible często produkuje odcinki, które są w 100%1 absorbujące. Są krótkie, więc jeśli coś przeoczę, próbując np. przejść przez ulicę, to zaraz się irytuję. Jeśli dam się znów wciągnąć kompletnie w materię odcinka, to przechodzę przez ulicę na ślepo.

99pi to nie jest radioreportaż, jaki pamiętacie, ale taki, jak sobie wyobrażaliście.

Odcinek startowy2: Holdout

Double Feature

https://doublefeature.fm/

Recenzowanie filmów to trzecie pod względem popularności zajęcie w Internecie. Drugie to recenzowanie gier komputerowych, a pierwsze — bycie padalcem. Pośród setek podobnych tematycznie podcastów Double Feature pozostaje niezmiennie moim wyborem numero uno. Połączenie osobowości prowadzących z ich wiedzą na temat filmów oraz wyborami samych tytułów do recenzji powoduje, że mogę często udawać wśród ludzi, że oglądałem filmy, przedrukowując językiem opinie, które usłyszałem w programie internetowym.

History of Philosophy Without Any Gaps

http://hopwag.podbean.com/

Podcast, którego tytuł mówi wszystko o zawartości. Jeden z niewielu, które radzę — jeśli już słuchać chcecie — słuchać od początku.

Philosophize This!

http://www.philosophizethis.org/

Podobnie jak podcast wyżej, ten też zajmuje się filozofią, ale jest mniej systematyczny (co nie jest złe dla odbiorców, którzy nie potrzebują 200 odcinków, aby dojść do tematu, o którym chcieli się dowiedzieć).

Odcinek startowy: Henry David Thoreau

Myths and Legends

http://www.mythpodcast.com/

Moja najnowsza perełka. Mity i legendy, historie, które znasz, w wersjach odmienionych przez kalejdoskop kultur, krajów i czasów.

Rekomendacja: przesłuchałem całość. Niektóre odcinki więcej niż raz.

The Reith Lectures

http://www.bbc.co.uk/programmes/b00729d9

Trudno to nawet nazwać podcastem. To seria wykładów, które odbywają się co jakiś czas z błogosławieństwa BBC. Zdecydowanie nie polecam jako „tła do pracy”, nawet gdy słucham na leżąco, wyskakuje mi żyła na czole od intelektualnych przysiadów.

Odcinek startowy: Democracy has a Bad Taste

Sztuka

The Pen Addict

https://www.relay.fm/penaddict

Pióra. Atrament. Notatniki. Plecaki. Piórniki. Pióra.

Czasem zdrajcy wspomną o długopisach, ale jednak pióra.

Moja ziemia obiecana.

Art Supply Posse

http://www.artsupplyposse.com/

Akwarele. Farby olejne. Ołówki. Pióra. Papier.

Czasem wywiady z ludźmi, którzy tych rzeczy używają.

Rozrywka

Listen to Lucy

http://www.acast.com/ft-lucy-kellaway

Dobrego komika można poznać po tym, że od lat bije po tym samym temacie, a ten puchnie ciągle w różnych miejscach, przynosząc radość obserwatorom tej masakry.

Lucy, felietonistka Financial Time, tydzień w tydzień nawiedza moją duszę esejem o tematyce w zakresach: koszmary komunikacji w biznesie, koszmary kultury w biznesie, koszmary kultury komunikacji w biznesie.

Każdego tygodnia łączę się z nią sercem w nienawiści do okrągłych przemów, które osuszone z przymiotników stają się mniej groźne i mniej ważne.

nerdy nocą

http://nerdynoca.pl/

Podcast po polsku! Kaja rozmawia z ludźmi, którzy znają się na różnych rzeczach. Audycje dla koneserów wiedzy wszelakiej. Jest na to wyraz: nerdów. Można słuchać za dnia.

Odcinek startowy: Sprawy atomowe

No Such Thing As A Fish

https://audioboom.com/channel/nosuchthingasafish

Wspominałem wyżej, że wielokrotnie polecam ludziom różne e-słuchowiska. To jedyne, które ma 100% sukcesu wśród słuchaczy.

Program komediowo-naukowy, brytyjskie akcenty, anegdoty o genitaliach. Triumwirat smaku.

Sawbones: A Marital Tour of Misguided Medicine

http://sawbones.libsyn.com/

Historia medycyny to historia nauki, tylko bardziej, bo była praktycznie połączona z przeżywalnością populacji — wynajdywanie pojazdu do latania napędzanego siłą mięśni zabijało najwyżej wynalazcę, przepisywanie upuszczania krwi na każdą przypadłość miało dużo gorsze konsekwencje. Każdy odcinek to naukowo-historyczna analiza jednego zabiegu czy leku, który z perspektywy czasu wydaje się być okropnym żartem.

The F Plus

https://thefpl.us/

Internet połączył wszystkich. Ten błąd, teraz nienaprawialny, pozwolił grupce ludzi zbierać się co jakiś czas i czytać rzeczy, które ludzkość wypisuje w Internecie.

Fora niszowych fetyszy, manifesty programowe partii rządzących nieistniejącymi mikro-narodami, pojedynki między fanami rzeczy głupich, to wszystko zostanie przeczytane ku uciesze gawiedzi.

Odcinek startowy: The Sound Quality Is Inaudible

Komputery, komputerów od cholery

Amigos Amiga Podcast

http://www.amigospodcast.com/search/label/podcast

Stary amigowiec i amigowy neofita grają w gry, to w sumie wszystko.

Garbage

http://garbage.fm/

Rzadki przypadek technologicznego podcastu, gdzie nie mieli się nagłówków z internetowej prasy kolorowej. Znaczy czasem też mówi się o gadżetach, ale nie tylko, gdyż obaj prowadzący są okazjonalnymi ulepszaczami projektu OpenBSD, możecie więc słuchać o tym, jakie problemy są z pisaniem sterowników do USB-ETH lub jak ciężko odpalić kernel BSD na Google Pixel.

Linux Voice Podcast

http://www.linuxvoice.com/

Audycja powiązana z magazynem (papierowym!) pod tym samym tytułem.

The Bike Shed

http://bikeshed.fm/

Podobne trochę tematycznie do Garbage, z tym że bardziej skłania się ku dyskusjom o niuansach języków programowania i aplikacjach pisanych przez prowadzących (którzy co jakiś czas się zmieniają — podcast ten jest piarowym frontem studia konsultacji dla klientów ze zjebanym produktem, więc ludzi do gadania jest wystarczająco). Obecnie główny przechył tematyczny to Rails, Rust i Eliksir.

Retro Asylum

http://castaway.media/retroasylum

Brytyjski program retro-komputerowy o wszystkim, choć z mocnym naciskiem na gry. Dwukrotny laureat nagrody „najlepszego podcastu na świecie” i ostateczny dowód na to, że głosowania w Internecie, a zwłaszcza ludzie biorący wyniki tych głosowań na serio, doprowadzą do świata, w którym nikt nie będzie szczęśliwy, a wszyscy będą źli.

Retro Computing Roundtable

http://rcrpodcast.com/episodes/

Cotygodniowy przegląd wydarzeń, nowinek i ciekawostek ze świata komputerów, które nie mają Snapchata. Takie „e-7 Dni Świat” dla starych ludzi.

Piłka Nożna Gola!

Długie lata broniłem się przed sprawdzaniem świata podcastowego pod kątem kopanej. A kiedy wreszcie się namówiłem, trafiłem na pole tak suche i zaniedbane, że nawet górska koza pokręciłaby łbem na ofertę zamieszkania. To oczywiście działo się w czasach przedrenesansowych, gdy jakąkolwiek jakość miały tylko audycje okołotechnologiczne.

Miesiąc temu, może trochę wcześniej, Filip po raz kolejny zasugerował mi, żebym dał szansę programowi o naszej lokalnej piłce. Ponieważ darzę polską piłkę podobną niechęcią co polskie podcasty3, ignorowałem jego sugestie z pełną świadomością popełnianego czynu. Aż któregoś dnia wyrzuciło mnie na kilkukilometrowy spacer i kliknąłem wtedy „plej”.

Skracając długą historię: zaskoczony pozytywnym doświadczeniem poszedłem po dokładkę.

Football Weekly

https://www.theguardian.com/football/series/footballweekly

Nacisk idzie głównie na futbol brytyjski (duh, Guardian), ale każda audycja zawiera też przegląd ważniejszych wydarzeń na boiskach europejskich. Całkiem zabawne, duża grupa komentatorów (w tym zagraniczni), odcinki specjalne, ogólnie: doskonały skrót dla ludzi, którzy przepuścili weekend piłkarski.

Hattrick

http://soundcloud.com/hattrickpl

Moją genezę podłączenia się pod to słuchowisko o kartofliskach już pisałem. Słucham, bo jest jakaś chemia wśród prowadzących, słucham też dlatego, że mam Schadenfreude na polską ligę. Pewnie to ukryty smutek po tym, że zatopiono (a raczej: załoga wycelowała armatę w dno statku i podpaliła lont) mi „mój” ełkaes, który obecnie błąka się po ligach tak niskich, że małe dziecko potrzebuje palców do ich policzenia.

Przykładowy odcinek: HattrickPL 34

The Final Third

http://soundcloud.com/thefinalthird

To trochę antyteza do Football Weekly, bo amatorski i irlandzko-szkocki, a trochę synteza, gdyż zarówno komentarz, jak i opinie pochodzą od ludzi, którzy rozumieją sport. No i bluzgają, bo trochę antyteza.

Zawsze Zielone

Polecane już we wcześniejszych odcinkach i „na zawsze w mym sercu”.

The Jeff and Casey Show

https://jeffandcaseyshow.com/jacs_all_podcast.rss

Anime World Order Podcast

http://www.animeworldorder.com/

Dan Carlin’s Hardcore History

http://www.dancarlin.com/

Overthinking It Podcast

https://www.overthinkingit.com/

Posłowie

Mój proces filtrowania podcastów jest bezlitosny. Jeśli moje serce nie trzepocze z ekscytacji na widok nowego odcinka, znaczy to, że już niedługo się z audycją pożegnam. Dość powiedzieć, że usunąłem kilka z tej listy podczas pisania. Otrzymujecie więc zestaw sprawdzony i wystarczy, że będziecie identyczni ze mną pod względem charakteru, ideałów i zainteresowań, aby cieszyć się nim bez ograniczeń.

A kto się nie cieszy, ma swoje własne propozycje lub po prostu chce wskazać literówki i lapsusy, może zawsze napisać mi e-mila.

  1. prawdziwi jednoprocentowcy
  2. taki odcinek, który mniej więcej reprezentuje, co się zwykle dzieje
  3. Jest to wynik mojego uprzedzenia, jak i złości, że sam nigdy nic nie zrobiłem. O szczegóły trzeba zapytać mojego psychoanalityka