niedziela, 9 grudnia 2018

Wałęsa krył pedofila?

WysokieObcasy czyli marka należąca do GazetyWyborczej opublikowała tekst o tym, że ksiądz Henryk Jankowski był pedofilem (nie czytałem). Temat podjęły inne media: Dorośli wiedzieli, że Jankowski -- jak mówili -- ,,gania za dziećmi''. Nagle został przeniesiony z parafii. ,,Po prostu zniknął, a potem stał się sławny''. Ks. Henryk Jankowski przez kilkadziesiąt lat wykorzystywał seksualnie dzieci. [...] Legendarny kapelan ,,Solidarności'' okazał się niebezpiecznym drapieżnikiem, który co najmniej od końca lat 60. przez kilka dekad wykorzystywał seksualnie dzieci. Od lat 90. na plebanii Jankowskiego pomieszkiwali ministranci i młodzi chłopcy. Podawali gościom alkohol, zostawali na noc, spali z Jankowskim w jednym łóżku. Widzieli to księża i politycy, ale nikt nie reagował.

No dobra kto to są ci Dorośli (zwani też księżmi i politykami, KiP): Lech Wałęsa, Bogdan Borusewicz, Jerzy Borowczak itd. itp. No ale na plebanii nie tylko bywali KiP, co najmniej należy dodać biznesmenów i dziennikarzy. Ci pierwsi to na przykład z okazji odbudowy całkiem niemałego kościoła i realizacji dziwacznego pomysłu bursztynowego ołtarza. A wśród tych drugich to i sam pan Adam Michnik się znajduje (lub jakiś jego podwłasny, który nie musiał przecież czekać 30 lat na zdemaskowanie potwora.)

Dlatego z ciekawością będę obserwował rozwój wydarzeń, ale i z pewnością że nasze skarby narodowe będą chronione do końca (ich lub chroniących). Pewności wszak nie ma co się stanie, jak na przykład Bolec nieopatrznie się wypuści za granicę do jakiegoś superpostępowego kraju...

poniedziałek, 3 grudnia 2018

Sshfs w MS Windows

Elka przeszła na Win10. Do niczego to jej nie jest potrzebne za wyjątkiem sytuacji kiedy pojedzie na konferencję i nie może sobie poradzić (na przykład z rzutnikiem). Wtedy jeżeli w ogóle jest jakiś konserwator od komputerów (zwany szumnie panem informatykiem), to odmawia kooperacji widząc nieznany sobie system. Absolutnie go rozumiem zresztą. Zwłaszcza, że odmian Linuksa są dziesiątki...

Anyway, wszystko działa w tym W10, za wyjątkiem aplikacji pn finanse domowe, którą od lat używamy. Aplikacja jest banalnie prosta ale rozproszona -- każdy wpisuje swoje wydatki ze swojego komputera, do pliku w uzgodnionym formacie. Plik jest jeden i znajduje się na swerwerze plików. Skrypt łączy się z serwerem przez fuse/sshfs. Plik wydatków jest redagowany za pomocą Emacsa. Wpisanie google: sshfs windows skutkuje znalezieniem m.in. strony Windows sshfs clients, polecającej na pierwszym miejscu SFTPNetDrive. Ściągnąłem/zainstalowałem działa, ale nie końca.

Zmienia uprawnienia pliku. Uzytkownik windziany, że tak powiem zapisuje plik jako read-only dla innych użytkowników. Być może można prościej ale ja wymyśliłem takie oto obejście: skrypt użytkownika linuksowego nie tylko będzie montował stosowny katalog z serwera, ale także poprawi uprawnienia. W tym celu niezbędne jest korzystanie z programu sudo. Żeby z kolei sudo nie pytał się o hasło należy go skonfigurować (plik /etc/sudoers), jak poniżej:

## instaluję sudo (bo nie było)
apt-get install sudo
## dodaję użytkownika tomek do grupy sudo
usermod -a -G sudo tomek
### modyfikuję  /etc/sudoers
## User privilege specification
#root    ALL=(ALL:ALL) ALL
### Należy dodać
#tomek   ALL=(ALL:ALL) NOPASSWD: ALL
### ORAZ
## zmodyfikować wiersz dotyczący
## grupy sudo (bez tego nie działa)
#%sudo   ALL=(ALL:ALL) NOPASSWD: ALL

Potem modyfikuję skrypt łączący z komputerkiem, dodając na końcu następujące polecenie poprawiające uprawnienia do plików:

ssh tomek@umbriel 'sudo chmod o+w /media/usbstick/Logs/common/ETC/*'

Teraz działa

środa, 28 listopada 2018

Podsumowanie listopada

Wizyta w rezerwacie Ptasi Raj (26/10/2018)

Jeszcze formalnie październik, ale warto też wspomnieć w zestawieniu listopadowym, bo byłem pierwszy raz w życiu w rezerwacie PtasiRaj (Sobieszewo w kierunku Górek Zachodnich). Wrażenia pozytywne (przyroda) i negatywne bo coś śmierdziało i hałasowało non stop praktycznie. Ludzi mało, bo zwykły weekday i po sezonie. Hałas był niewielki--bardziej stanowił kontrast pomiędzy pierwotną przyrodą rezerwatu--człowiek myślał że jest w Białowieży a tu coś stuka i wierci w oddali (stocznie a głos po wodzie się niesie). Puściutka-dzika plaża, ale na horyzocie widać Port Północny albo instalacje Lotosu.

Teren zagospodarowany w tym sensie że są wytyczone ścieżki edukacyjne, tablice z opisami flory/fauny, dwie wieże obserwacyjne (lornetkę należy mieć koniecznie) a nawet restauracja (przed rezerwatem oczywiście) Wracając do smrodu, to może dzień był pechowy--też nie tak że jakość strasznie cuchnęło ale było czuć że bynajmniej nie jest to zapach bryzy-od-morza.

Stutthoff -- 1-sza wizyta (27/10/2018)

Pierwszy raz w Niemieckim KL w ogóle (nigdy nie byłem w Auschwitz/Majdanku itp). Nie lubię takich miejsc oglądać ale się reklamowali że jest wystawa czasowa pn `Prawo i zagłada' o roli Policji w Trzeciej Rzeszy w Zbrodniach (jak mniemam) No więc ponieważ interesuję się historią, a temat wydał się ciekawy to postanowiłem pojechać i obejrzeć. Upewniłem się czy w Sobotę działają. Działają tyle że krócej, bo mają imprezę plenerową później.

Jadę (rowerem). Dojeżdżam o 12:20 (wg info mieli działać do 13:00).
-- Wystawa?--no dziś zamknięta
-- Nosz kurna toż się pytałem
-- No to pracujemy ale wystawa zamknięta wyjątkowo bo mamy koncert o 18:00

Czyli typowe w PL-państwówce. Mieli pretekst to sobie poszli do domu o 12.45 (bo już o tej godzinie zamknęli bramę) bynajmniej nie pomagać przy imprezie (która zaczynała się za 5h). Ale jak już tam byłem, to wlazłem na teren. Niewiele tam jest do oglądania--prawie nic. Chyba że coś pominąłem ale raczej nie, by się w oczy rzucało. Nie ma atmosfery grozy miejsca zbrodni--taka łąka a la ośrodek wypoczynkowy tyle że płot z drutem kolczastym. Krematorium niby jest ale teraz to palenie zmarłych nie jest czymś niezwykły, izby w (bodajże czterech) barakach co zostały niezniszczone/albo je odbudowali -- przerobione na sale muzealne, urządzenia sanitarne nieliczne (jedna łazienka konkretnie).

Wiele instalacji (ogród obozowy) ewidentnie nieoryginalna. To co jest to gabloty z papierami i jakimiś drobnymi przedmiotami typu łyżka czy but...

Kopalino #1 (02/11/2018)

Pierwszy raz w życiu--ciekawe miejsce, zwłaszcza po sezonie.

Tutaj są zdjęcia.

Do Jankowa k/Kowal 03/11/2018

Tam w sklepie rowerowym A. Wojtasa (m.in. masażysta Bora-HansGrohe (B-HG)) fajna impreza była, o której się dowiedziałem z FB. Trwało to 2 godziny, w tym czasie właściciel sklepu (czyli Wojtas) opowiedział (w detalach) jak wyglądało odżywianie kolarzy podczas jednego (6 godzinnego) etapu Tirreno-Adriatico (na którym R. Majka zajął 2-gie miejsce BTW). W przerwach między gadaniem gotował ryż (z owocami--przepis na zdjęciu), z którego potem zrobił kostki po 60--70g (25g suchego ryżu podobno). Masa wskazówek jak uzyskać właściwą konsystencję, jak opakować żeby łatwo odpakować na rowerze itp...

Przy okazji wiele ciekawostek opowiedział na przykład na temat diety Sagana (że misie Haribo lubi i makaron z manufaktury Martelli co kosztuje B-HG całkiem okrągłą kwotę), że B-HG ma autobus restauracyjny, tj. kolarze jedzą w autobusie, a nie w hotelu (szybciej i lulu spać), że B-HG ma samochód meblowy i przed etapem taki samochód jedzie do hotelu i wymienia materace, kołdry, itp w pokoju na swoje. Że B-HG zatrudnia 80 ludzi (do obsługi 30 kolarzy) i ma budżet 22mln EUR z czego 4mln idzie na TdF.

Tutaj są zdjęcia.

Sztutowo #2 06/11/2018

Byłem w Sztuthoffie raz jeszcze. Wykorzystałem okazję bo Elka jechała do Łomży to mnie odstawiła do Nowego Dworu Gdańskiego więc praktycznie miałem w jedną stronę podwózkę. Obleciałem cały obóz. Poprzednio pominąłem parę rzeczy typu komora gazowa. Byłem też na tej wystawie co ją chciałem obejrzeć, ale okazała się w sumie lipą. Takie tam Niemieckie bicie się w piersi (jak już wszyscy potencjalnie do oskarżenia nie żyją)--bo wystawa jest Niemiecka. Ogólnie znane fakty; no i mała--kilkanaście plansz.

Ciekawostkowo: nie było ochrony, wlazłem ot tak. Do tej pory jak tam byłem dwa razy bodajże, to zawsze opiernicz od ochrony, że rower, nie wolno itp. Bo jak już się przejdzie przez bramę, to na terenie obozu nie ma żadnego dozoru, tylko napisy że kamery są...

Wystawa niemiecka była w szklarni. Poprzednio jak byłem, to nie mogłem wejść, bo szklarnia była zamknięta. Komuś kurna nie chciało się pójść i zamka przekręcić--bo reszta obozu była dostępna, a szklarnia -- nie wiedzieć czemu -- nie.

Tutaj są zdjęcia

Otwarcie mostu na W. Sobieszewską 10/11/2018

Przypadek polegał na tym że pojechałem celem zwiedzenia rezerwatu ,,Ptasi Raj'' a nie na otwarcie (o którym nie miałem pojęcia). Nawet chciałem poczekać i obejrzeć uroczystość ale chaos był i nie było wiadomo kiedy się zacznie. Otóż organizatorzy nie pomyśleli i moim zdaniem źle zaplanowali otwarcie. Postawili mikrofony na początku mostu i przewidzieli otwarcie-podniesienie jako gwóźdż programu (bo to zwodzony jest most). Widząc tłum na moście kazali ludziom stanąć przed mostem, co znakomicie pozbawiłoby wielu możliwości obejrzenia czegokolwiek. Więc przez 15 minut trwały targi żeby tłum się cofnął, a że się nie cofał to sobie odpuściłem. Tam z boku był plac było tam zrobić przemówienia a potem otworzyć most (na przykład.)

Co do smrodu, to był mniejszy i w innym miejscu. Las przy plaży pełen śmieci i ludzi (bo to sobota była). Za to nie było hałasu ze stoczni...

Tutaj są zdjęcia. A tutaj jest filmik.

Cmentarz francuski (12/11/2018)

Impreza na 100 lecie rozejmu kończącego 1-szą wojnę światową. Ja sie znam z konsulem honorowym rep. Francuskiej (też rowerzysta) to poszedłem z ciekawości. Miał być ambasador i w ogóle...

Przyjechałem grubo za wcześnie, bo mi się godziny pomyliły, ale nie byłem pierwszy. Młody mężczyzna jakiś chodził między grobami w zielonym berecie, ale ubrany w cywilne łachy. Sylwetka sportowa, ogolony łep na rekruta... Oho myślę ochrona ambasadora. Ale potem przyszedł drugi, starszy, o lasce z całą klatą w medalach w takim samym berecie. A potem następny i jeszcze następny, razem z 10 było, w różnym wieku. Się okazało że to Polacy, bo po polsku gadali. No to się przyjrzałem bliżej bo naszywkę każdy miał na ręce:

Legion Entrangere.

O-żesz. Mówili perfekt polszyzną (do siebie bo jak się ustawili do warty to przeszli na francuski) i bez przekleństw, a nie kurwa-kurwa co drugie słowo jak nie przymierzając b. premier Belka. Czyli selekcja jest i byle kogo do Legii nie biorą.

Ciekawostka #2. Były 2 przemówienia: krótsze ambasadora i dłuższe biskupa Głodzia, który pierdyknął mowę na 10 minut (albo i lepiej), ale o czym mówił to ja nie wiem, bo było po francusku... Szczena nie tylko mi chyba opadała bo generalnie ma on nie najlepszą opinię.

Tutaj są zdjęcia.

13/11/2018 Cmentarz angielski

Podobna impreza, ale w Malborku bo tam jest cmentarz Brytyjskiej Wsp. Narodów. Słabiej wypadło. Liczyłem na kobziarzy, a przyszedł tylko pluton w mundurach polowych + pułkownik z ambasady. Orkiestry nie było, tylko na trąbce sygnały grali. Za to miejscowi się starali (a w GDA nie--z UM/Urzędu Wojewódzkiego to ja w GDA nikogo nie widziałem.)

Był jeden kombatant (na zdjęciu), ksiądz anglikański. Po uroczystości Angole złożyli wieniec (z plastikowych maków) na jednym grobie. Pytam się czy to ktoś z ich jednostki (bo tam tradycja -- oddziały po 300 lat istnieją) ale nie rodzina przysłała/dała wieniec to położyli.

Powrót w ulewnym (miejscami) deszczu. Takie były w sumie prognozy ale miałem nadzieję. Jakoś takoś jednak nie przemarzłem (dobra kurtka przeciw deszczowa) i doturlałem się z Malborka do GDA, a tam do SKM-ki bo już mi się nie chciało przez miasto jechać.

Tutaj są zdjęcia

15/11/2018 Kopalino#2/Mechowo

Drugi raz się kopsnąłem w tym kierunku. Pierwszy raz byłem w Grotach Mechowskich. Atrakcja taka sobie--bilet trzeba kupić żeby nie tyle wejść--bo słowo grota to na wyrost jest -- co podejść do groty... Nie kupiłem:-) Spieszyło mi się, poza tym płot jest 5m od groty i jest ażurowy więc widać co jest za płotem...

Tutaj są zdjęcia.

Upgrade roweru

Cichcem zrobiłem upgrade swojej bryki CX kupując koła Campagnolo Vento (drugie od dołu:-) 1100 PLN nowe). Fajne koła za 400 PLN, używane, ale w dobrym stanie. Jeszcze nawet opony dodał gość, ale te akurat 23mm i dupiate (Hutchinson za 40 PLN nowe) w zasadzie do wywalenia, mimo że w dobrym stanie, m.in. dlatego, że ja definitywnie przeszedłem na 25mm.

Ponadto wymieniłem sztycę, bo w starej już dwa razy złamała się śruba mocująca. Niby firmowa (Amoeba), a miała IMO defekt konstrukcyjny: śruby mocujące siodło to zaledwie #5. No ktoś przesadził. Minimum 6mm i się nie łamią. Tu z kolei kupiłem niby karbonowego Ritcheya, a nieoficjalnie chińską podróbkę tegoż (za 170 PLN nie kupi się Richeya). Że chiński to wskazuje także to, że sztyca ma ciut za małą średnicę i się osuwała w rurze podsiodłowej. Okleiłem ją taką taśmą przeciwogniową z warstwą aluminium (klej ma toto dobry) i jakby teraz nie spada...

Jeszcze dokupiłem pedały jednostronne Kellys za 99 (przecenione z 300 PLN na Allegro). Fajne pedały. Wreszcie przypadkiem nowe siodło 4za za 95 PLN (czyli Ridley--żółte do żółtego roweru!) Kiedyś używałem podobnego siodła i się pałąk łamał--kijowe było, ale tamto to był Stratus a to Cirrus (wizualnie to to samo:-). Ten Cirrus to nawet jest tańszy--ale to może i lepiej, bo tańsze to często są trwalsze

Rower waży teraz 9,9kg (opony 35mm, dętki też niczego sobie) co uważam za b. dobry wynik.

niedziela, 4 listopada 2018

Towarzyszka partyjna Widmann ma pomysł

Pełnomocnik rządu federalnego ds. Integracji, Annette Widmann-Mauz (CDU), wzywa do edukacji seksualnej osób ubiegających się o azyl w Niemczech, po tym jak 7 Syryjczyków zostało aresztowanych i oskarżonych o gwałt we Fryburgu.

Ciekawe czemu tylko osób ubiegających się o azyl w Niemczech a nie wszystkich gwałcicieli? Jak równość to równość.

Nb. i celem przypomnienia: jak nam takie Parteigenossinen Widman rajfurzyły tzw. ,,dzieci-z-Aleppo'' to następujące argumenty podnoszono: że jak nie to xenofobia, że jak nie to strzał w stopę bo ubogacenie kulturowe, że jak nie to bezczelna niewdzięczność (forsa wzięta z UE zobowiązuje do wykonywania poleceń centrali--ex Tusk m.in. mówił takie cóś bez ogródek). No to teraz się wyjaśniło, że to co wzielim to by się teraz zwróciło w formie wydatków na bezpieczeństwo i edukację ,,dzieci-z-Aleppo''. Pan Bóg czuwał tym razem nad Polską i wybory 2015 skończyły się jak się skończyły...

sobota, 27 października 2018

Jeden obraz wart więcej niż tysiąc słów

Dla propagandzistów z Wiertniczej/Czerskiej/PolitrukaPL na pewno. Ale tego tam nie zobaczycie bo wtedy ich wyznawcy by dostali rozdwojenia jaźni.

Brakuje tylko Tuska + Bono.

BTW zdjęcie pochodzi ze spotkania w Stambule 27.10.2018 czyli wczoraj (jedyny element dorysowany to oczywiście kretyńskie badge/odznaki pn. KONSTYTUCJA)

czwartek, 25 października 2018

Wybory 2018. Różnica w liczbie mandatów do Sejmików

Powyborczo. Primo: szkoda, że PiSom te kamery nie wyszły byłoby się z czego pośmiać oglądając debili ze świeczkami (innego pożytku z zainstalowania -- przy założeniu #1kamera na jedną komisję -- 27tys kamer nie widzę).

Ale do rzeczy: dane pobrane z PKW (na Wikipedii za 2014 mają dokładnie takie same, za 2018 nie sprawdzałem)

require(ggplot2)

#d <- read.csv("mandaty.csv", sep = ';',  header=T, na.string="NA");
# Albo po prostu bo danych mało
# https://www.datamentor.io/r-programming/data-frame/
x <- data.frame("komitet" = c("PIS", "PO", "PSL", "SLD", "INNI"),
   "y2018" = c(254,194,70,15,19),
   "y2014" = c(171,179,157,28,20) )

# różnica w liczbie uzyskanych mandatów
d$diff <- d$y2018 - d$y2014 

ggplot(d, aes(x= komitet, y=diff, fill=komitet)) +
  geom_bar(stat="identity") +
  scale_fill_manual("legend",
    values = c("PIS" = "#421C52", "PO" = "blue",
    "PSL" = "green", "SLD" = "red", "INNI" = "pink")) +
    geom_text(aes(x=komitet, y=diff, label=diff),
    hjust=0, vjust=-0.25, size=3.5) +
ggtitle ("Mandaty sejmików wojewódzkich 2018--2014 (zmiana)")

BTW, jeżeli protokoły komisje obwodowe wysłały (zapewne elektronicznie) do PKW góra w poniedziałek (w mojej już poniedziałek-rano okleili kopią drzwi), to co niezawisłe Hermelińskie robiły we wtorek i środę? Niestety tego prostego pytania żaden z tzw. dziennikarzy (aka specjalistów od pierdołowatych njusów czyli #pierdokontentu) nie zadał.

A mnie ono ciekawi.

BTW2: ten wpis jest 500 w blogu. Wychodzi jakieś 45/rok średnio (z tendencją spadkową).

czwartek, 18 października 2018

Śmieciowe sondaże przedwyborcze

Znakomita większość publikowanych sondaży pomija szacowanie frekwencji; czasami dodaje się zaklęcie zdecydowani wyborcy. Widziałem jeden sondaż, w którym podano ilu jest tych zdecydowanych -- 80%. Jak się to ma do realiów i jaka jest wartość prognoz opartych na założeniu, że do urn pójdzie 80% uprawnionych, no to poniższa tabela daje pojęcie (P oznacza oczywiście wybory parlamentarne a S samorządowe):

Rok           | P2015 S2014 P2011 S2010 P2007 S2006 P2005 P2001
--------------+------------------------------------------------
%Uprawnionych | 50,92 47,21 48,92 47,32 53,88 45,99 40,57 44,23

Wybory wójtów/burmistrzów/prezydentów

Analiza eksploracyjna wyborów wójtów/burmistrzów/prezydentów. W PL wybiera się radnych w wyborach do rad powiatów/rad gmin (oba ciała IMO zbędne), radnych sejmików wojewódzkich oraz uwaga: wójtów/burmistrzów/prezydentów (WBP) na poziomie gmin. O ile wybory sejmików kierują się tym samym mechanizmem co wybory sejmowe to wybory WBP są większościowe -- każdy może wystartować i wygrać. Do tego taki WBP ma dużą władzę więc warto być WBP. Takich wyborów w PL jest 2477 -- tyle ile gmin. W zależności od statusu gminy w jednych wybiera się wójta a w innych prezydenta czy burmistrza. Mówiąc konkretnie wójtów jest 1547, burmistrzów 823 a prezydentów 107. Poniższa tabela zestawia dane dotyczące kandydatów w wyborach 2018/2014/2010

  Rok      N   1KN   1K%   2KN   2K%   >4N    >4%     śr
  ------------------------------------------------------
  2018  6965   329  13,30  849  34,30  262  10,58   2,81
  2014  8019   245   9,90  666  26,90  471  19,00   3,25
  2010  7776   303  12,20  683  27.57  430  17,36   3,14

Jak na moje to kandydatów za dużo to się nie zgłasza, do tego (w tym roku/w tych wyborach) w 13,30% gmin jest jeden, a w 34,30% dwóch (co daje co najwyżej dwóch w prawie połowie wyborów WBP). Do tego tendencja jest jakby nie w tę stronę co trzeba: mniej kandydatów ogółem, więcej gmin z małą liczbą kandydatów, mniej gmin z dużą liczbą kandydatów. Można podsumować że demokracja na lokalnym poziomie słabnie...

Ilustruje to wykres krzywych gęstości liczby kandydatów na urząd WBP (dla każdego roku oddzielna krzywa).

## ramka g ma następującą strukturę: razem;teryt;rok
g$r <- as.factor(g$rok)
p <- ggplot(g, aes(x=razem, color=r)) + geom_density() +
labs(title="Krzywa gęstości liczby kandydatów na urząd wójta/burmistrza/prezydenta",
x="Liczba kandydatów", 
y = "Gęstość", color="Rok")

Dane są tutaj

poniedziałek, 15 października 2018

Czy Platforma Obywatelska to kryptonaziści?

Po występach przewodniczącego Juliusa Schetyny można było mieć wątpliwości, że to jednorazowy amok. Ale znaleźli się wszakże podwładni Juliusa, którzy postanowi pokazać, że są równie mądrzy jak szef, a nawet dużo mądrzejsi. Naprawdę trzeba nie mieć mózgu w ogóle, żeby przerobić Goebbelsowski plakat z podpisem Pracuj z Niemcami a będziesz uratowany i takie coś publikować z dumą na Twitterze. No a przecież wcześniej był/jest w tej partii ważna figura pn. Protasiewicz co się na bagażowym wyżywała we Franfurcie wrzeszcząc na niego Heil Hitler czy jakoś tak. No już trzech mamy KN (kryptonazistów) -- jeszcze dwóch i będzie tylu co w słynnym reportarzu w #WaffelTV, co taką gównoburzę wywołał w styczniu br.

Znamienne jest tak nawiasem mówiąc milczenie takich opertkowych figur jak pan Bodnar (na przykład), który miał gębę pełną frazesów a nawet listy dramatyczne do premiera i ministra sprawiedliwości pisał, kiedy ww. WaffelTV ujawniła ww. groźny spisek 5 idiotów w lesie (Konieczne wydaje się opracowanie nowej, kompleksowej strategii mającej na celu zwalczanie rasizmu i ksenofobii w Polsce -- uważa Rzecznik Praw Obywatelskich, Adam Bodnar) Teraz nie ma problemu operetkowy pan Bodnar, i nie widzi żadnej potrzeby a to zapewne z tej prostej przyczyny, że skończonym idiotą okazał się chłop z ferajny, a nie żaden tam anonimowy zresztą nacjonalista.

Jeżeli ktoś nie wie czemu Juliusz/Julius a nie Grzegorz. Ano temu że, Dr. Goebbels nie tyle wymyślił co udowodnił empirycznie, że kłamstwo powtórzone 1000 razy staje się prawdą. Mianowicie w tekstach publikowanych w gazecie Der Angriff przekręcał systematycznie i uporczywie imię szefa Berlińskiej Policji, określając go Izydorem (co ma/miało żydowskie konotacje w Niemczech podobno), aż większość Berlińczyków faktycznie uznała w końcu, że Bernhard Weiss ma na imię Izydor.

środa, 10 października 2018

Koniec pobierania danych wyborczych

Dobrnąłem w końcu do finału pobierając ostatecznie ze strony PKW dane dotyczące siedmiu wyborów, które odbyły się w latach: 2015, 2014 (samorządowe), 2011, 2010 (samorządowe), 2007, 2006 (samorządowe), 2005.

Wyniki wcześniejszych wyborów nie są już dostępne na poziomie komisji obwodowych (a przynajmniej ja nie potrafię takowych odszukać). Protokoły z wyborów z 2006 roku też nie były dostępne, ale udało się je w części odtworzyć ze stron z wynikami kandydatów (zawierającymi liczbę głosów oddanych na kandydata w poszczególnych komisjach obwodowych).

Dla każdych wyborów wykreśliłem histogram poparcia dla mainstreamowych partii: PSL, PO, PiS oraz SLD. Zgodnie z oczekiwaniami rozkłady poparcia są jednomodalne, prawostronnie symetryczne, ale z dwoma wyjątkami: rozkład poparcia dla PO jest bimodalny i ta tendencja wydaje się stała. Rozkład poparcia dla PSL z roku 2014 (cud nad urną) różni się -- na zasadzie znajdź element niepasujący do pozostałych -- od sześciu pozostałych rozkładów poparcia dla tej partii (czemu to już inna historia).

Dane są tutaj

wtorek, 2 października 2018

Pobranie danych z wyborów samorządowych 2010

Co wybory to inaczej oczywiście...

Wyniki wyborów 2010 są na stronie http://wybory2010.pkw.gov.pl/. Punktem wyjścia jest zaś strona z wynikami dla województwa postaci http://wybory2010.pkw.gov.pl/geo/pl/020000/020000-o-020000-RDA-2.html?wyniki=1, w której wiodące 02020000 to kod teryt województwa a 2 przed .html to numer okręgu wyborczego. Zatem pobranie wszystkich stron `okręgowych' sprowadza się do:

#!/usr/bin/perl
#
use LWP::Simple;
#
my $uribase = 'http://wybory2010.pkw.gov.pl/geo/pl';
@Woj = ("02", "04", "06", "08", "10", "12", "14", "16",
  "18", "20", "22", "24", "26", "28", "30", "32");
@Okr = (1,2,3,4,5,6,7,8,9,10); ## nadmiarowo (max jest 8 chyba)

for $w (@Woj) {
  for $o (@Okr) {
    $url = "$uribase/${w}0000/${w}0000-o-${w}0000-RDA-${o}.html?wyniki=1";
    $file = "ws2010_woj_${w}_${o}";
    getstore($url, $file);
    print STDERR "$url stored\n";
  }
}

Teraz się okazuje że każdy taki plik zawiera odnośniki postaci /owk/pl/020000/2c9682212bcdb46c012bcea96efe0131.html. Każdy taki plik opisuje kandydata startującego w wyborach. Ich pobranie jest równie banalne:

#!/usr/bin/perl
#
use LWP::Simple;
use locale;
use utf8;
binmode(STDOUT, ":utf8");
use open IN => ":encoding(utf8)", OUT => ":utf8";

$baseURI="http://wybory2010.pkw.gov.pl";
$file = $ARGV[0];

while (<>) {
  chomp();
  if (/(owk\/[^<>"]*)/) {
     $url= "$baseURI/$1";
     if (/(owk\/[^<>"]*)[^<>]*>([^<>]*)/) {
       $who = "$2"; $who =~ s/ //g;
       $who =~ tr/ĄĆĘŁŃÓŚŻŹ/ACELNOSZZ/;
       $who =~ tr/ąćęłńóśżź/acelnoszz/;
     } else {$who = "XxYyZz"; }

     $outFile = "owk_${file}__${who}";
     getstore($url, $outFile);
     print STDERR "$url stored ($outFile)\n";
  }
}
## pobranie wszystkich owk-URLi to:
## for i in ws2010_woj* ; do perl pobierz-owk.pl $i ; done

W plikach `owk' są linki do protokołów z wynikami z poszczególnych komisji. Są to linki postaci: /obw/pl/3206/bacbedd03197794e2e1e8e438bff87e1.html. Należy je wszystkie pobrać (URLe nie pliki) i posortować usuwając duplikaty. Powinno być takich URLi około 25--27 tysięcy (tyle ile komisji):

#!/usr/bin/perl
#
$baseURI="http://wybory2010.pkw.gov.pl";
$file = $ARGV[0];

while (<>) {  chomp();
  if (/(obw\/[^<>"]*)/) {
     $url= "$baseURI/$1";
     if (/(obw\/[^<>"]*)[^<>]*>([^<>]*)/) {
         $obwNr = "$2"; }
     $outFile = "${file};${obwNr}";
     print "$url;$outFile\n";
} }
## for i in owk_2010* ; do perl pobierz-obw.pl $i ; done > proto0.csv
## awk -F';' '{print $1";"$3}' proto0.csv | sort -u > protokoly.csv
## wc -l protokoly.csv
## 25464 protokoly.csv

Każdy URL jest postaci /obw/pl/0201/051595429cc31a526f8b2455602ab929.html. Te 0201 to pewnie teryt powiatu, ale reszta wydaje się losowa więc nie da się ustalić jakiegoś schematu URLi protokołów, bo go nie ma po prostu. Teraz postaje pobrać te 25464 plików-protokołów z komisji obwodowych. Na wszelki wypadek będę zapisywał te protokoły wg schematu: proto_ws_2010_terytPowiatu_nrkomisji:

#!/usr/bin/perl
##
use LWP::Simple;
open (O, "protokoly.csv") || die "No protokoly.csv!";
while (<O>) { chomp();
  ($url, $nrk) =  split /;/, $_;
  $_ =~ m#http://wybory2010.pkw.gov.pl/obw/pl/([0-9][0-9][0-9][0-9])#;
  $teryt = $1;
  $outFile = "proto_ws_2010_${teryt}_$nrk";
  getstore($url, $outFile);
  print STDERR "*** $url stored ($outFile)\n";
}
close(O);
## time perl get-proto.pl

Mi się ściągało 62 minuty 30 sekund.

Wybory 2014 i jeszcze więcej rozkładów

Rozkład odsetka głosów nieważnych (definiowanego jako głosy nieważne / (głosy ważne + nieważne)) w wyborach samorządowych w 2014. Pierwszy histogram dotyczy całej Polski (27455 komisji), drugi województwa pomorskiego (1856) a trzeci Mazowieckiego (3574).

#!/usr/bin/Rscript
# Skrypt wykreśla histogramy dla danych z pliku ws2014_komisje.csv
# (więcej: https://github.com/hrpunio/Data/tree/master/ws2014_pobranie_2018)
#
par(ps=6,cex=1,cex.axis=1,cex.lab=1,cex.main=1.2)
komisje <- read.csv("ws2014_komisje.csv", sep = ';',
       header=T, na.string="NA");

komisje$ogn <- komisje$glosyNiewazne  / (komisje$glosy + komisje$glosyNiewazne) * 100;

summary(komisje$glosyNiewazne); fivenum(komisje$glosyNiewazne);
sX <- summary(komisje$ogn);
sF <- fivenum(komisje$ogn);
sV <- sd(komisje$ogn, na.rm=TRUE)
skewness <- 3 * (sX[["Mean"]] - sX[["Median"]])/sV

summary_label <- sprintf ("Śr = %.1f\nMe = %.1f\nq1 = %.1f\nq3 = %.1f\nW = %.2f", 
  sX[["Mean"]], sX[["Median"]], sX[["1st Qu."]], sX[["3rd Qu."]], skewness)

## ##
kpN <- seq(0, 100, by=2);
kpX <- c(0, 10,20,30,40,50,60,70,80,90, 100);
nn <- nrow(komisje)

h <- hist(komisje$ogn, breaks=kpN, freq=TRUE,
   col="orange", main=sprintf ("Rozkład odsetka głosów nieważnych\nPolska ogółem %i komisji", nn), 
   ylab="%", xlab="% nieważne", labels=F, xaxt='n' )
   axis(side=1, at=kpN, cex.axis=2, cex.lab=2)
   posX <- .5 * max(h$counts)
text(80, posX, summary_label, cex=1.4, adj=c(0,1))

## ##
komisje$woj <- substr(komisje$teryt, start=1, stop=2)

komisjeW <- subset (komisje, woj == "22"); ## pomorskie
nn <- nrow(komisjeW)
sX <- summary(komisjeW$ogn); sF <- fivenum(komisjeW$ogn);
sV <- sd(komisjeW$ogn, na.rm=TRUE)
skewness <- 3 * (sX[["Mean"]] - sX[["Median"]])/sV

summary_label <- sprintf ("Śr = %.1f\nMe = %.1f\nq1 = %.1f\nq3 = %.1f\nW = %.2f", 
  sX[["Mean"]], sX[["Median"]], sX[["1st Qu."]], sX[["3rd Qu."]], skewness)

h <- hist(komisjeW$ogn, breaks=kpN, freq=TRUE,
   col="orange", main=sprintf("Rozkład odsetka głosów nieważnych\nPomorskie %i komisji", nn), 
   ylab="%", xlab="% nieważne", labels=T, xaxt='n' )
   axis(side=1, at=kpX, cex.axis=2, cex.lab=2)
   posX <- .5 * max(h$counts)
text(80, posX, summary_label, cex=1.4, adj=c(0,1))

komisjeW <- subset (komisje, woj == "14"); ## mazowieckie
nn <- nrow(komisjeW)
sX <- summary(komisjeW$ogn); sF <- fivenum(komisjeW$ogn);
sV <- sd(komisjeW$ogn, na.rm=TRUE)
skewness <- 3 * (sX[["Mean"]] - sX[["Median"]])/sV

summary_label <- sprintf ("Śr = %.1f\nMe = %.1f\nq1 = %.1f\nq3 = %.1f\nW = %.2f", 
  sX[["Mean"]], sX[["Median"]], sX[["1st Qu."]], sX[["3rd Qu."]], skewness)

h <- hist(komisjeW$ogn, breaks=kpN, freq=TRUE,
   col="orange", main=sprintf("Rozkład odsetka głosów nieważnych\nMazowieckie %i komisji", nn), 
   ylab="%", xlab="% nieważne", labels=T, xaxt='n' )
   axis(side=1, at=kpX, cex.axis=2, cex.lab=2)
   posX <- .5 * max(h$counts)
text(80, posX, summary_label, cex=1.4, adj=c(0,1))

Wyniki są takie oto (indywidualne wykresy tutaj: #01 #02 #03):

Rozkłady odsetka poparcia dla PSL/PiS/PO w wyborach samorządowych w 2014 w całej Polsce, w miastach/poza miastami oraz w poszczególnych województwach. Poniższy skrypt generuje łącznie 60 wykresów słupkowych:

#!/usr/bin/Rscript
# Skrypt wykreślna różnego rodzaju histogramy dla danych z pliku ws2014_komitety_by_komisja_T.csv
# (więcej: https://github.com/hrpunio/Data/tree/master/ws2014_pobranie_2018)
#
showVotes <- function(df, x, co, region, N, minN) {
   ## showVotes = wykreśla histogram dla województwa (region)
   kN <- nrow(df)
   sX <- summary(df[[x]], na.rm=TRUE);
   sV <- sd(df[[x]], na.rm=TRUE)
   ## współczynnik skośności Pearsona
   skewness <- 3 * (sX[["Mean"]] - sX[["Median"]])/sV

   summary_label <- sprintf ("Śr = %.1f\nMe = %.1f\nq1 = %.1f\nq3 = %.1f\nS = %.1f\nW = %.2f", 
     sX[["Mean"]], sX[["Median"]],
     sX[["1st Qu."]], sX[["3rd Qu."]], sV, skewness)

   if (minN < 1) {
   t <- sprintf("Rozkład głosów na %s\n%s ogółem %d komisji", co, region, kN ) } 
   else { t <- sprintf("Rozkład głosów za %s\n%s ogółem %d komisji (N>%d)", co, region, kN, minN ) } 

   h <- hist(df[[x]], breaks=kpN, freq=TRUE, col="orange", main=t, 
     ylab="%", xlab="% poparcia", labels=F, xaxt='n' )
     axis(side=1, at=kpN, cex.axis=2, cex.lab=2)
   ## pozycja tekstu zawierającego statystyki opisowe
   posX <- .5 * max(h$counts)
   text(80, posX, summary_label, cex=1.4, adj=c(0,1))
}

## Wczytanie danych; obliczenie podst. statystyk:
komisje <- read.csv("ws2014_komitety_by_komisja_T.csv", 
   sep = ';', header=T, na.string="NA");

komisje$ogn <- komisje$glosyNiewazne  / (komisje$glosy 
   + komisje$glosyNiewazne) * 100;

summary(komisje$PSL); summary(komisje$PiS); summary(komisje$PO);
fivenum(komisje$PSLp); fivenum(komisje$PiSp); fivenum(komisje$POp);

## ## ###
par(ps=6,cex=1,cex.axis=1,cex.lab=1,cex.main=1.2)
kpN <- seq(0, 100, by=2);
kpX <- c(0, 10,20,30,40,50,60,70,80,90, 100);
kN <- nrow(komisje)
region <- "Polska"
minTurnout <- 0

## cała Polska:
showVotes(komisje, "PSLp", "PSL", region, kN, minTurnout);
showVotes(komisje, "PiSp", "PiS", region, kN, minTurnout);
showVotes(komisje, "POp",  "PO",  region, kN, minTurnout);

## Cała Polska (bez małych komisji):
## ( późniejszych analizach pomijane są małe komisje)
minTurnout <- 49
komisje <- subset (komisje, glosyLK > minTurnout); 
kN <- nrow(komisje)

showVotes(komisje, "PSLp", "PSL", region, kN, minTurnout);
showVotes(komisje, "PiSp", "PiS", region, kN, minTurnout);
showVotes(komisje, "POp",  "PO",  region, kN, minTurnout);

## Typ gminy U/R (U=gmina miejska ; R=inna niż miejska)
komisjeW <- subset (komisje, typ == "U"); 
kN <- nrow(komisjeW)
region <- "Polska/g.miejskie"
showVotes(komisjeW, "PSLp", "PSL", region, kN, minTurnout);
showVotes(komisjeW, "PiSp", "PiS", region, kN, minTurnout);
showVotes(komisjeW, "POp",  "PO",  region, kN, minTurnout);

komisjeW <- subset (komisje, typ == "R"); 
kN <- nrow(komisjeW)
region <- "Polska/g.niemiejskie"
showVotes(komisjeW, "PSLp", "PSL", region, kN, minTurnout);
showVotes(komisjeW, "PiSp", "PiS", region, kN, minTurnout);
showVotes(komisjeW, "POp",  "PO",  region, kN, minTurnout);

## woj = dwucyfrowy kod teryt województwa:
komisje$woj <- substr(komisje$teryt, start=1, stop=2)

cN <- c("dolnośląskie", "dolnośląskie", "kujawsko-pomorskie",
 "lubelskie", "lubuskie", "łódzkie", "małopolskie", "mazowieckie",
 "opolskie", "podkarpackie", "podlaskie", "pomorskie", "śląskie",
 "świętokrzyskie", "warmińsko-mazurskie", "wielkopolskie",
 "zachodniopomorskie");
cW <- c("02", "04", "06", "08", "10", "12", "14", "16", "18",
 "20", "22", "24", "26", "28", "30", "32");

## wszystkie województwa po kolei:
for (w in 1:16) {
  wojS <- cW[w]
  ###region <- cN[w];
  region <- sprintf ("%s (%s)", cN[w], wojS);

  komisjeW <- subset (komisje, woj == wojS); ##

  showVotes(komisjeW, "PSLp", "PSL", region, kN, minTurnout);
  showVotes(komisjeW, "PiSp", "PiS", region, kN, minTurnout);
  showVotes(komisjeW, "POp",  "PO",  region, kN, minTurnout);
}
## ## koniec

Dla całej Polski wyniki są następujące:

Indywidualne wykresy zaś tutaj: #01 #02 #03 #04 #05 #06 #07 #08 #09 #10 #11 #12 #13 #14 #15 #16 #17 #18 #19 #20 #21 #22 #23 #24 #25 #26 #27 #28 #29 #30 #31 #32 #33 #34 #35 #36 #37 #38 #39 #40 #41 #42 #43 #44 #45 #46 #47 #48 #49 #50 #51 #52 #53 #54 #55 #56 #57 #58 #59 #60):

poniedziałek, 1 października 2018

Wybory samorządowe 2014/2018. Profil wiekowy kandydatów cd

Rozkłady wieku kandydatów (2014/2018) i radnych wybranych do sejmików wojewódzkich 2014.

require(ggplot2)
### ### ###
co <- "Wiek kandydatów do sejmików wojewódzkich (2014 / Polska)"

## deklaracja końców klas (hist)
wB <- c(18,20,25,30,35,40,45,50,55,60,65,70,75,80,95);
wZ <- c(36,38,40,42,44,46,48,50,52,54,56);
wD <- seq(18, 92, by=2);

komitety <- "DB = Demokracja Bezpośrednia | RN = Ruch Narodowy | NPKM = Nowa Prawica JKM";

k <- read.csv("kandydaci_ws_2014.csv", sep = ';',  header=T, na.string="NA", dec=",");

with (k, table(komitet))

aggregate (k$wiek, list(Numer = k$komitet), fivenum)
## analiza dotyczy tylko kandydatów z komitetów ogólnopolskich
kandydaci <- subset (k,
    (komitet == "PSL" | komitet == "DB" | komitet == "PiS" | komitet == "PO" |
     komitet == "RN" | komitet == "NPKM" | komitet == "SLDLR"));
kandydaciPL <- kandydaci
kNum <- nrow(kandydaciPL) 
kNum

with (kandydaci, table(komitet))

aggregate (kandydaci$wiek, list(Numer = kandydaci$komitet), fivenum)

sumS <- summary(kandydaci$wiek)
sumV <- sd(kandydaci$wiek)
summary_label <- sprintf ("Śr = %.1f\nMe = %.1f\nQ1 = %.1f\nQ3 = %.1f\nS = %.1f",
        sumS[["Mean"]], sumS[["Median"]],
        sumS[["1st Qu."]],  sumS[["3rd Qu."]],  sumV)

#par() ## przegląd parametrów
# ps = stopień pisma
par(ps=11,cex=1,cex.axis=1,cex.lab=1,cex.main=1.2)
h <- hist(kandydaci$wiek, 
   breaks=wB, 
   freq=TRUE,
   col="orange", main=co,
   ylab="liczba kandydatów", xlab="wiek", labels=T, xaxt='n')
   axis(side=1, at=wB)
   text(80, 600, summary_label, cex = .8, adj=c(0,1))

par(ps=6,ce=2,cex.axis=2,cex.lab=2,cex.main=2)
h <- hist(kandydaci$wiek, 
   breaks=wD, 
   freq=TRUE,
   col="orange", main=co, ylab="liczba kandydatów", xlab="wiek", labels=T, xaxt='n' )
   axis(side=1, at=wB, cex.axis=2, cex.lab=2)
   text(80, 600, summary_label, cex=0.4, size=3, pos=3, adj=c(0,1))

### ### ###

aggregate (kandydaci$wiek, list(Numer = kandydaci$nr), fivenum)
aggregate (kandydaci$wiek, list(Numer = kandydaci$komitet), fivenum)

### ### ###

ggplot(kandydaci, aes(x=komitet, y=wiek, fill=komitet))  +
   geom_boxplot() +
   ylab("Wiek") +
   xlab("Komitet") +
   annotate(geom="text", x = 1, y = 90, hjust=0, size=3,
   label = komitety ) +
   guides(fill=FALSE) ;

### ### ### Pomorskie TERYT=22 ### ### ###
co <- "Wiek kandydatów do sejmików wojewódzkich (2014 / Pomorskie)"

kandydaci <- subset (kandydaci, (woj == "22" ))
aggregate (kandydaci$wiek, list(Numer = kandydaci$komitet), fivenum)

ggplot(kandydaci, aes(x=komitet, y=wiek, fill=komitet))  +
   geom_boxplot() +
   ylab("Wiek") +
   xlab("Komitet") +
   annotate(geom="text", x = 1, y = 90, hjust=0, size=3,
    label = komitety ) +
   guides(fill=FALSE) ;

sumS <- summary(kandydaci$wiek)

summary_label <- sprintf ("Śr = %.1f\nMe = %.1f\nQ1 = %.1f\nQ3 = %.1f",
    sumS[["Mean"]], sumS[["Median"]], sumS[["1st Qu."]],  sumS[["3rd Qu."]])

## przywrócenie wartości parametrów
par(ps=11,cex=1,cex.axis=1,cex.lab=1,cex.main=1.2)

h <- hist(kandydaci$wiek, 
   breaks=wB, 
   freq=TRUE,
   col="orange", main=co, xlab="wiek", ylab="liczba kandydatów", labels=T, xaxt='n')
   axis(side=1, at=wB)
   text(80, 40, summary_label, cex = .8, adj=c(0,1))

with (kandydaci, table(komitet))

### ## ###
kandydaciPL$okrN <- paste (kandydaciPL$woj, "o", kandydaciPL$okr)
a <- aggregate (kandydaciPL$wiek, list(Numer = kandydaciPL$okrN), fivenum)

h <- hist(a$x[,3], 
   breaks=wZ, 
   freq=TRUE,
   col="orange",
   main="Mediana wieku kandydatów wg okręgów [Polska 2014]",
   xlab="wiek", ylab="liczba okręgów", labels=T, xaxt='n')
   axis(side=1, at=wZ)
   text(80, 40, summary_label, cex = .8, adj=c(0,1))

## ## ### radni (czyli wybrani)
radni <- read.csv("radni_ws_2014.csv", sep = ';',
     header=T, na.string="NA", dec=",");

sumS <- summary(radni$wiek)
sumV <- sd(radni$wiek)

summary_label <- sprintf ("Śr = %.1f\nMe = %.1f\nQ1 = %.1f\nQ3 = %.1f\nS = %.1f",
    sumS[["Mean"]], sumS[["Median"]], sumS[["1st Qu."]],  sumS[["3rd Qu."]],  sumV)

h <- hist(radni$wiek,
   breaks=wB,
   freq=TRUE,
   col="orange", 
   main="Wiek radnych do sejmików wojewódzkich 2014", 
   ylab="liczba radnych", xlab="wiek", labels=T, xaxt='n')
   axis(side=1, at=wB)
   text(80, 80, summary_label, cex = .8, adj=c(0,1))
 

środa, 26 września 2018

Wybory samorządowe 2018. Profil wiekowy kandydatów

Na stronie https://wybory2018.pkw.gov.pl/pl/geografia#general_committee_stat jest informacja, że w wyborach na radnych sejmików wojewódzkich bierze udział/zostało zarejestrowanych 7076 kandydatów. Zaczynając od tej strony można się doklikać do stron dla każdego województwa oraz okręgu. Są to odpowiednio strony tworzone według schematu:

https://wybory2018.pkw.gov.pl/pl/geografia/220000#geo_committee_stat
https://wybory2018.pkw.gov.pl/pl/geografia/220000/voiv_council/1

Strona okręgu zawiera listę kandydatów a jej HTML jest tak nieskomplikowany, że zamiana na na przykład plik CSV jest banalnie prosta.

Po ściągnięciu 85 ,,stron okręgowych'' i ich zamianie na CSV, faktycznie otrzymałem plik składający się z 7076 wierszy, z których każdy jest postaci:

woj;okr;komitet;nr;kandydat;wiek;skad;oswidczenie;uwagi
02;o1;SLD-LR;1;SIKORA Arkadiusz;45;Oleśnica;;

Dalszą analizę przeprowadziłem wykorzystując R:

k <- read.csv("kandydaci_ws_2018_3.csv", sep = ';',  header=T, na.string="NA", dec=",");
with (k, table(komitet))
Komitet liczba kandydatów liczba okręgów
BS 447 62
K15 675 84
KW INICJATYWA OBYWATELSKA POWIATU TARNOGÓRSKIEGO 31 4
KW STOWARZYSZENIA LEX NATURALIS 12 2
KW STRONNICTWA PRACY 6 1
KW ŚLĄSKIEJ PARTII REGIONALNEJ 85 12
KW ŚLONZOKI RAZEM 40 5
KW WSPÓLNA MAŁOPOLSKA 51 KW WYBORCÓW AKCJA NARODOWA 27 5
KW WYBORCÓW ISKRA 38 6
KW WYBORCÓW JEDNOŚĆ NARODU -- WSPÓLNOTA 118 18
KW WYBORCÓW AGNIESZKI JĘDRZEJEWSKIEJ 5 1
KW WYBORCÓW MNIEJSZOŚĆ NIEMIECKA 31 4
KW WYBORCÓW POLSKIE RODZINY RAZEM 28 4
KW WYBORCÓW PROJEKT ŚWIĘTOKRZYSKIE BOGDANA WENTY 30 4
KW WYBORCÓW SPOZA SITWY 23 4
KW WYBORCÓW Z DUTKIEWICZEM DLA DOLNEGO ŚLĄSKA 45 5
KW ZJEDNOCZENIE CHRZEŚCIJAŃSKICH RODZIN 40 7
KW ZWIĄZKU SŁOWIAŃSKIEGO 173
PiS 722 85
PO-N 722 85
PSL 722 85
RAZEM 549 85
RN 528 79
SLD-LR 713 85
WiS 448 63
WwS 574 77
ZIELONI 349 57

Dalszą analizą objęto 10 komitetów, które zarejestrowały kandydatów w ponad połowie okręgów wyboczych (WsS to Wolność w Samorządzie; WiS to Wolni i Solidarni a BS oznacza Komitet pn Bezpartyjni Samorządowcy):

aggregate (k$wiek, list(Numer = k$komitet), fivenum)

wB <- c(18,20,25,30,35,40,45,50,55,60,65,70,75,80,95);
summary_label <- paste (sep='', "Średnia = ", sprintf("%.1f", sumS[["Mean"]]),
  "\nMediana = ", sumS[["Median"]],
  "\nQ1 = ", sumS[["1st Qu."]],  "\nQ3 = ", sumS[["3rd Qu."]] )

## wykres słupkowy
h <- hist(kandydaci$wiek, 
   breaks=wB, 
   freq=TRUE,
   col="orange", main="Wiek kandydatów do sejmików...",
   ylab="liczba kandydatów", xlab="wiek", labels=T, xaxt='n')
   axis(side=1, at=wB)
   text(80, 600, summary_label, cex = .8, adj=c(0,1))

   ## wykres pudełkowy
ggplot(kandydaci, aes(x=komitet, y=wiek, fill=komitet))  +
   geom_boxplot() +
   ylab("Wiek") +
   xlab("Komitet") +
   annotate(geom="text", x = 1, y = 90, hjust=0, size=3,
    label = "WwS = Wolność w Samorządzie | ...") +
   guides(fill=FALSE) ;
#komitetminq1Meq3max
1BS18.036.044.057.081.0
2K1518.032.042.053.082.0
3PiS18.040.051.059.079.0
4PO-N18.041.051.060.075.0
5PSL20.044.055.062.080.0
6RAZEM18.028.034.042.087.0
7RN18.027.034.048.081.0
8SLD-LR18.044.058.065.083.0
9WiS18.038.050.061.585.0
10WwS18.024.031.043.083.0
11ZIELONI18.034.044.055.080.0

To samo dla woj. pomorskiego:

kandydaci <- subset (kandydaci, (woj == "22" ))
aggregate (kandydaci$wiek, list(Numer = kandydaci$komitet), fivenum)

## itd...
1BS23.036.544.047.572.0
2K1523.037.050.058.073.0
3PiS21.042.549.063.571.0
4PO-N22.039.050.060.575.0
5PSL28.049.062.068.080.0
6RAZEM19.029.033.538.087.0
7RN21.027.031.549.066.0
8SLD-LR18.050.059.062.575.0
9WwS19.027.032.038.567.0
10ZIELONI19.039.048.054.067.0

Dane i skrypty są tutaj.

niedziela, 23 września 2018

Żuławy w Koło 2018 (how it unfolded)


Trasa z kierunkiem wiatru

Nonsensowny drogowskaz na Rubno Wlk.

00:20 wracam do domu z niesamowitej imprezy urodzinowej kol. BL zorganizowanej w Blues Club Gdynia.

01:05 idę spać. Straciłem z pół godziny (żeby rano zaoszczędzić 15 minut) usiłując kupić bilet do Malborka przez Internet ale się nie udało. System nie działał. Tzn. prawie działał. Naciśnięcie ostatniego guzika skutkowało zwisem...

04:20 wstaję. 04:55 jadę na dworzec PKP, kupuję bilet i jadę pociągiem do Malborka. Wysiadam 06:10, przedtem jem śniadanie z pudełka w pociągu.

W Malborku jest już szaro. Z mocnym wiatrem w plecy jadę do Nowego Dworu Gdańskiego (circa 25 km). 07:15 jestem na miejscu. Start za 45 minut bo podobnie jak w imprezie Kociewskiej plan jest taki żeby zapierdzielać w grupie dopóki się da, a na bufetach stawać i jechać z następną grupą. Więc żeby tych grup do podczepienia się było potencjalnie jak najwięcej chcę zacząć z pierwszą. Pierwszy bufet zamierzam odpuścić, bo jest na 37 km czyli blisko startu.

Pogoda jest niezła. Dużo lepsza niż była prognozowana. Miało być zimno, wietrznie i miało padać. Jest około 13C, czyli nie aż tak bardzo zimno, faktycznie wieje, ale nie pada i się nie zanosi żeby padało, a to najważniejsze.

07:50 ustawiam się na linii startu. Trochę wcześnie, ale chcę być w pierwszej grupie, bez konieczności wpychania się poza kolejnością. Wśród czekających rowerzyści-turyści na rowerach nie do końca stricte szosowych.

Startujemy z lekkim opóźnieniem o 08:05.

Tempo pierwszego kilometra turystyczne dyktują ci na turystycznych. Inaczej niż w zeszłym roku -- słynny start z kol. Wiktorem -- kiedy to startując w grupie #2 już od początku mieliśmy wściekły zapieprz. Wygląda na to, że najwięksi ściganci się nie spieszą i ustawiają się w kolejnych grupach na starcie. No i dobrze...

Po pierwszym kilometrze zmiana. Prowadzących i tempa. Jedziemy na wschód z wiatrem jakieś 33--35 km. Miło i przyjemnie, do czasu aż doganiają nas ci superściganci. Zabieram się z nimi. Tempo może i specjalnie nie wzrasta, ale to tylko dlatego, że teraz mamy wiatr boczny, a potem czołowo-boczny. Wieje całkiem mocno na wschód/północny-wschód (na Kaliningrad he, he). Zapieprz całkiem konkretny, aż do skrętu na drogę 502 w Tujsku. Tutaj poprawia się jakość asfaltu, ale też tempo wzrasta. Z jednym takim mocnym w nogach, ale powiedzmy słabym w taktyce odpadamy. Mocarze pojechali. Za nami z kolei też nikogo nie widać. Mój kompan jest tak mocny, że gdyby miał lepszą taktykę, to bez problemu by jechał w pierwszej grupie, a tak to mnie tylko holuje (zmian nie daję, o czym go uprzedzam).

Dojeżdżamy do bufetu #1. Ponieważ sytuacja się rozwinęła, tak jak się rozwinęła sugerują żeby stanąć. Pierwszy bufet w Jantarze tak trochę na uboczu, z drogi go nie widać. Zajeżdżamy. Okazuje się, że grupa czołowa też tu stanęła. Bufet super zaopatrzony zresztą: ciasta domowej roboty, naleśniki, bułki z czymśtam. Nawet jakaś zupa. Jakby spróbować tylko każdej z potraw to by człowiek nie był w stanie dalej jechać. Jem dwa kawałki ciasta i dwa naleśniki. Dwa następne w kieszeń...

Jadę dalej. Nawet zaczynam z grupą czołową znowu, ale za duże tempo więc odpuszczam. Dogania mnie za to całkiem mocny gość a potem jeszcze jeden. Jedziemy zgodnie tym razem aż do Nowej Kościelnicy. Tutaj wyłącza mi się kamera (bo zapomniałem włączyć guziczek `Ładuj' w Powerbanku--zawsze czegoś zapomnę). Mówię tym, z którym jadę żeby chwilę zwolnili, bo chcę ustalić co dalej z kamerą, ale oni nie potrafią wolno--no trudno zostałem sam, ale z tyłu ktoś kręci, więc się nie napinam tylko czekam aż mnie dogonią.

Znowu dwóch, ale innych. Słabsi niż ci co nie chcieli czekać i do tego słabi technicznie, że tak powiem. Ja tam po zmianie się za nich chowam oni nie--na kole nie jadą, tylko obok albo 10m za. Mimo tego trzymają się, pomimo tego wściekłego bocznego wiatru. Jedziemy wzdłuż Wisły aż do Mątowów (Dorota z Mątew), tyle że po drodze wreszcie urywam swoich partnerów, ale mam za to dwóch innych. Jednego już znam, jechałem z nim wcześniej. Przeoczyłem bufet #2, on stanął a teraz mnie doszedł (z kolegą).

Za Mątowami skręt jakby na wschód, na wschód, na Miłoradz. Teraz wiatr jest w plecy aż do bufetu #3 (raptę parę kilometrów). Jedziemy we trzech spacerowo, tym bardziej że jeden z nas ma kapcia (ale takiego że idzie jechać--zmieni dętkę na bufecie). Jest generalnie przekonanie że od Miłoradza będzie miło i przyjemnie z wiatrem. Potem się okazało że nie było i nawet nie było szans żeby było przy tym kierunku wiatru (o tym później). Wykorzystując przerwę w zapieprzu uświadamiam współścigantom gdzie są. Że są w Mątowach, wsi w której urodziła się słynna bł. Dorota. Pytam się czy słyszeli o Dorocie. Nie. No to ja że to matka 9-ga dzieci, która kazała się zamurować w celi, gdzie zmarła. No bo jak taki/taka się już zamurował, to no-way, wychodził już tylko nogami do przodu. -- Ale po co? pyta współścigant. -- Ku chwale Bożej -- odpowiadam -- dawniej ludzie tak mieli. -- No ale coś z tego było? A to nie wiem -- odpowiadam :-)

Bufet w Miłoradzu całkiem zwyczajny: chleb z marmoladą i smalcem. Ale dają też kopytka na słodko. Swoim zwyczajem nie rozsiadam się, jem kopytka i dalej sam--dogonią mnie. I faktycznie doganiają w Pogorzałej Wsi. Stąd jest z wiatrem wzdłuż Nogatu prosto do Malborka. Zapierdzielamy całkiem żwawo, a mnie się już przstało chcieć, jeszcze dociągam do Zamku i odpuszczam na zakręcie DK55 na Kościeleczki. Co się będę spinał--z wiatrem sobie pojadę te ostatnie 20km sam (sobie myślę).

Bym znał profil trasy dokładnie, to bym nie miał takich złudzeń. Znowu wieje nieprzyjemny boczny wiatr (aż do Lubiszewa czyli aż praktycznie do mety). Generalnie z tym wiatrem to masakra była. Kilka odcinków z wiatrem, reszta zwykle z nieprzyjemny bocznym albo nawet pod wiatr.

Kilka kilometrów jadę sam, ale dogania mnie następna grupa. Ci są z firmy, są jednakowo ubrani, całkiem mocni i wiedzą co to jazda w grupie. Jadę z nimi prawie do końca, czyli do Lubiszewa. Tam odpuszczam, bo tempo wzrasta a mi się już nie chce (pobudka 4:20 ostatecznie--więc mam wymówkę)

13:02 jestem na mecie. Jem makaron i do Malborka na pociąg. Jest pod wiatr, non-stop. No ale ja się nie spinam. Mam pociąg 15:02 i dużo czasu, tyle że jak się jedzie 18kmh, po przejechaniu 25 +135 = 160 km to trochę się dłuży droga, by się już chciało skończyć.

Dojeżdżam jakoś tak 14:40. Się okazuje, że pociąg jest 14:57 i całkiem sporo ludzi w kolejce do kasy. Kupuję bilet, jest 14:50.

W Kałdowie dosiada się współścigant z pierwszej grupy. Podobno był drugi, jechał circa 4:20 (ja circa 4:57). Na mecie się ociągał, wyjechał o 14:00 i ledwo zdążył pod ten wiatr. By pociąg nie stawał w Kałdowie (nie wszystkie stają, bo to mały przystanek jest bez kas i budynku, a nie żadna stacja), to by nie zdążył. Uświadamiam go jakie miał szczęście :-) NB ja też mogłem w Kałdowie wsiadać, ale wolałem do Malborka, bo to różnie bywa (w sensie, że w Malborku bardziej komfortowo się do pociągu wejdzie--co jest istotne jak się ma takiego klamota jak rower)...

W domu jestem circa 16:20. Minęło 12h od pobudki...

Filmik dając pojęcie jak (ciężko) było :-) jest tutaj. BTW odszukaj na googleMaps Rubno Wlk jeżeli nie wiesz czemu drogowskaz w Marzęcinie wydaje się bezsensowny.

środa, 19 września 2018

UE, PL i (rzekome) wartości

Poezja na unijnych salonach. Timmermans poleciał "Itaką"

Autor: Katarzyna Szymańska-Borginon

Ubrał się w szaty Odyseusza i chce wciąż utrzymywać się na fali. Nawet przez kolejnych pięć lat. A do tego potrzebna mu jest Polska.

Wiceprzewodniczący Komisji Europejskiej Frans Timmermans przyznał, że takie ma plany, używając przy tym poetyckiego porównania. Okazuje się, że gdy polityk w przypływie szczerości zaczyna cytować wiersze, to mówi coś bardzo prawdziwego o sobie samym i swoich rzeczywistych intencjach. Podczas konferencji prasowej po wysłuchaniu Polski w Radzie UE dziennikarka zapytała Fransa Timmermansa, czy nie obawia się, że wysłuchania Polski będą się mnożyć, a rezultatu nie będzie.

Wtedy polityk przypomniał wiersz Konstandinosa Kawafisa "Itaka". To jeden z moich ulubionych poetów -- pochwalił się komisarz. Nagrodą dla Odyseusza nie jest powrót do Itaki, ale sama podróż, którą odbył -- interpretował wiersz. W ten sposób opisałbym artykuł siódmy --dodał wiceprzewodniczący KE. Tłumaczył następnie, że najważniejsze w procedurze artykułu siódmego jest nie to, czy będzie głosowanie w Radzie UE (w sprawie sankcji, czy uznania Polski za kraj niepraworządny), ale "działania", "wspólny wysiłek", "dialog", "sam proces". Nadzwyczajna szczerość. Komisarz otwarcie więc powiedział to, co mówi się w  brukselskich kuluarach po cichu. Cel artykułu siódmego, czyli głosowanie w Radzie UE jest mniej istotny (bo i tak na razie nie ma szans realizacji), ważna jest sama "podróż", czyli "grillowanie Polski" i stałe "nękanie" poprzez wysłuchania, czy rezolucje. Ciekawe, czy Timmermans chciał to powiedzieć, czy powiedział za dużo. Bo na pewno nie służy to mobilizowaniu Warszawy.

W pewnym momencie Frans Timmermans nie miał nawet problemu z utożsamieniem siebie z Odyseuszem. Gdy dziennikarz zwrócił uwagę, że Odyseusz nie był ograniczony liczącą pięć lat kadencją, komisarz od razu podjął temat. A kto powiedział, że kończę w przyszłym roku? Nie mam zamiaru odejść. Mam zamiar kontynuować -- tłumaczył. I znowu, wpadając w sidła metafory, Timmermans potwierdził oficjalnie to, o czym szeptano od dawna. Zamierza powtórnie ubiegać się o stanowisko holenderskiego komisarza. Takie wyznanie na konferencji prasowej, gdy głównym tematem jest kwestia praworządności w Polsce - oznacza tylko jedno - połączenie obu spraw. W takiej sytuacji staje się jasne, że ostre stanowisko w sprawie Polski, poprawia Timmermansowi notowania. Być może nawet pomaga w robieniu kariery.

W kontekście zbliżających się wyborów europejskich (także na stanowiska komisarzy) sensowne jest więc pytanie o prawdziwe intencje wiceprzewodniczącego Timmermansa.

Jeżeli najważniejsza jego zdaniem jest "podróż" (grillowanie Polski), to wyjaśnia się dlaczego, nie było widać po stronie Timmermansa woli osiągnięcia kompromisu z Polską, w momencie, kiedy stanowisko objął Mateusz Morawiecki.

Teraz już sprawy zaszły za daleko. Z winy Warszawy, ale także dlatego, że Timmermans chce zrobić karierę kosztem Polski. I nie można udawać, że się tego nie widzi. Na zakończenie. Lepiej, żeby politycy nie cytowali poezji na konferencjach prasowych.

A tak to widzą w FT. Mniej poezji więcej konkretów. Co bardziej kuriozalne tezy wytłuściłem

The intervention of two big EU powers underscores the bloc's internal divisions over the rise of illiberal parties to government in central Europe and elsewhere. = Problemem nie jest są zatem Europejskie Wartości tylko to że nie ci rządzą co trzeba

We hope that Poland acts constructively and does not take actions which cannot be changed afterwards = nie twój zasrany interes Teutonie (zwłaszcza w kontekście poprzedniego zdania)

Tuesday's hearing in Brussels ended inconclusively = kogo zatem to oświadczenie dotyczy? No wygląda że nie PL tylko tych co nie dość entuzjastycznie chcą się dołączyć

Cały (prawie) tekst brzmi jak następuje:

Germany and France urge Poland to halt judicial overhaul

Germany and France have joined forces to press Poland to back down over a contentious judicial overhaul in the latest sign of the widening EU rift over the alleged authoritarian drift of some member states.

Michael Roth, Berlin's Europe minister, said in a joint statement with Paris on Tuesday that the Polish case had become ``more urgent than ever'' in the bloc's fight for fundamental values including the rule of law.

The Franco-German comments came in a hearing by the EU's other 27 member states of a case launched by the European Commission in December over Warsaw's possible breaches of EU values. The intervention of two big EU powers underscores the bloc's internal divisions over the rise of illiberal parties to government in central Europe and elsewhere.

The commission is expected to up the pressure on Poland on Wednesday by launching a separate complaint to the European Court of Justice over the judicial changes, EU diplomats said.

Mr Roth deplored the lack of progress made in five EU ministerial meetings so far on the so-called Article 7 case launched by the commission against Poland. He said the matter had become still more urgent as Warsaw had pressed ahead with rules to force some Supreme Court judges to retire and had begun steps to replace them.

We hope that Poland acts constructively and does not take actions which cannot be changed afterwards,'' he said.

Tuesday's hearing in Brussels ended inconclusively. Member states critical of Poland's action need a four-fifths majority of the EU27 to press the case forward -- a high bar. A move to impose sanctions such as suspending Warsaw's voting rights would require unanimity, which Hungary has said it will block. [...]

Frans Timmermans, EU commissioner, said there was not ``much good news'' from the hearing as Poland's government had failed to address concerns about its supreme court law in particular.

``The situation has not improved'' said Mr Timmermans.

He insisted that the power of the Article 7 process was not about getting member states to agree to sanction Poland but engage Warsaw in a process of dialogue.

``The reward for Ulysses is not arriving home but the voyage to get there. That is how I would like to describe Article 7. We have not reached Ithaca yet''.

Żuławy w Koło 2018

Się tak rozochociłem, że zapisałem się na Żuławy w Koło 2018 (99 PLN). W ramach przygotowań, że tak powiem taktycznych postanowiłem rozpoznać możliwości przeciwnika:-) Konkretnie ustalić jak jechali ci co się zapisali, a co już startowali w ŻwK w roku 2017 albo 2016. Zadanie zatem polega na odszukaniu na liście zgłoszeń tych co się zapisali na edycję 2018 i jednocześnie ukończyli ŻwK w latach 2016/2017. Oczywiście nie ręcznie, tylko automatem:

## poniższe ściąga plik z listą zapisanych
wget 'http://www.czasomierzyk.pl/zapisy2016/zulawywkolo/index.php?akcja=lista' -O ZwK2018.out

Plik HTML ma tak prostą strukturę, że jego zamiana (za pomocą wyrażeń regularnych) na CSV jest banalna. Jak już mam ten plik CSV, to porównuję go do połączonych wyników z lat 2017/2016 (też w formacie CSV). Skrypt mam co porównuje pliki CSV:

perl join_csvs.pl -fn1 ZwK201809190908.csv  -fs1 1,2 -fn2 ZwK16_17.csv -fs2 1,2

Porównuje pliki ZwK201809190908.csv oraz ZwK16_17.csv, w oparciu o (wspólną) wartości dla kolumn nr 1 oraz nr 2 (w tym przypadku są to kolumny zawierające nazwisko i imię). Innymi słowy fs1 c1,c2..., to klucz główny, a fs2 c1,c2, to klucz obcy. Skrypt wypisuje połączone wiersze odpowiadające tym wierszom dla, których klucz główny = klucz obcy. Na dziś (19 września) takich wierszy wypisał 55, (na 104 zgłoszenia na dystansie 140km), ale pomijam tych co startowali kiedyś na najkrótszym dystansie lub tych, którzy startowali wprawdzie na najkrótszym, ale mieli średnią mniejszą niż 24kmh (odpada w ten sposób 10 zostaje 45). Na koniec plik jest zapodawany do prostego skryptu rysującego wykres słupkowy:

z <- read.csv("ZwK_2018_vs_2017.csv", sep = ';',
   header=T, na.string="NA", dec=".");

s140 <- summary(z$speed)

z <- subset (z, ( speed > 16.0 )); ## bez maruderów

# wykres słupkowy
h <- hist(z$speed,
  breaks=c(18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35),
  freq=TRUE,
  col="orange",
  main="Dystans: 140 (biorący udział w latach 2017-16)",
  xlab="Prędkość średnia w latach 2017--16 [kmh]",ylab="L.kolarzy",
  labels=T, xaxt='n' )
  axis(side=1, at=c(18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35))
  text(38, 37, summary_label, cex = .8, adj=c(1,1) )

Jak widać paru ludków w okolicach 30kmh jest. Będzie za kim jechać.

wtorek, 18 września 2018

Wybory 2014 (drugie pobranie danych)

Ściągnąłem protokoły z wyborów do sejmików wojewódzkich jeszcze raz. Punktem wyjścia były indywidualne pliki dla każdej gminy pobrane ze strony samorzad2014.pkw.gov.pl. Te pliki zawierają zsumowane wyniki wyborów dla danej gminy, ale także zawierają adresy URL do plików z wynikami na poziomie poszczególnych komisji (z tej gminy). Mają one adres URL wg schematu:

http://samorzad2014.pkw.gov.pl/357_rady_woj/0/NR_TERYT_GMINY

Mając zestawienie numerów TERYT gmin pobieram indywidualne pliki za pomocą prostego skryptu:

use LWP::Simple;
## Na wejściu lista 6-cyfrowych numerów gmin
while (<>) { $nn++;
   chomp();
   $File{"$_"}++;
   $url = "http://samorzad2014.pkw.gov.pl/357_Sejmiki_wojewodztw/0/$_";

   if ( $File{"$_"} > 1 ) {
   $file = "./html/$_" . "$File{$_}_"  . ".html"; }
   else { $file = "./html/$_" . ".html"; }

   getstore($url, $file);
   print STDERR "$nn = $url => $file... stored\n";
}

Z tych plików wydłubuję numery komisji (które są wartościami atrybutu href do pliku z protokołem i mają postać 321_protokol_komisji_obwodowej/NRKOMISJI) i zapisuję do pliku o strukturze:

020101;321_protokol_komisji_obwodowej/NRKOMISJI

Teraz z plików komisji odczytuję adresy URL protokołów wyborów do sejmików. Ten URL wygląda następująco:

020101;321_protokol_komisji_obwodowej/NRKOMISJI/rdw_COŚTAM

Przy czym COŚTAM to cyfra, np. rdw_5. Problem, że ta cyfra nie zawsze jest taka sama, stąd konieczność przeczytania pliku i odszukania w nim odsyłacza do protokołu wyborów do sejmików. Na szczęście pliki HTML są w miarę proste i do odszukania tego co trzeba wystarczy proste wyrażenie regularne. Poniższy skrypt po odszukaniu odsyłacza pobiera plik protokołu i zapisuje w katalogu ./protokoly_sw/:

#!/usr/bin/perl
use LWP::Simple;
my $log = "protokoly_sw.log";
open (LOG, ">$log") || die ("Nie mogę pisać do $log");

while (<>) {  $nn++;
  chomp();
  ($teryt, $postfix, $nrk) = split /[;\/]/, $_;

  unless ( -f "./protokoly_sw/$nrk" ) {
     $file = "./protokoly_sw/$nrk";

     open (LOGP, "./komisje/$nrk");

     while (<LOGP>) { chomp();
        if (/([^\/]*protokol_komisji.*)">Sejmik/) {## URL do protokołu
           $prot_url = $1;
           print "$1\n";
           last
        }
     }
     close (LOGP);
     $url = "http://samorzad2014.pkw.gov.pl/$prot_url";
     getstore($url, $file);
     print LOG "$nn = $url => $file stored\n";
     print STDERR "*** $nn = $url => $file stored\n";
  } else { print STDERR "*** $url => $file stored already\n"; }
}

Teraz analizuję pobrane protokoły zapisując informacje do trzech plików .csv: ws2014_komisje.csv ws2014_listy.csv oraz ws2014_kandydaci.csv. Pierwszy zawiera informacje zbiorcze takie jak liczba uprawnionych czy liczba głosów ważnych dla każdej komisji, drugi informacje zbiorcze o liczbie głosów oddanych na każdą listę wyborczą w każdej komisji a trzeci o liczbie głosów oddanych na każdego kandydata w każdej komisji. W związu z tym:

wc -l ws2014_*csv
  3062457 ws2014_kandydaci.csv
   301876 ws2014_listy.csv
    27393 ws2014_komisje.csv

Tj. ws2014_komisje.csv ma 27393 wierszy (i tyle jest komisji); ws2014_listy.csv ma 301876, a ws2014_kandydaci.csv ponad 3mln wierszy (wynik kandydata w każdej komisji, w której był zarejestrowany). Skrypt (nieco uproszczony) wydłubujący potrzebne informacje z pliku protokołu wygląda następująco:

#!/usr/bin/perl
open (LOG, ">>ws2014_log.log");

open (L, ">>ws2014_listy.csv");
open (K, ">>ws2014_kandydaci.csv");
open (X, ">>ws2014_komisje.csv");

$fileName = $ARGV[0];
$fileName =~ s/(\/[^\/]+)$/$1/;

while(<>) {
   chomp();
	    
   if (/<h2>/) {  $mode = 'I'; 

       while (<>) {
          chomp();
	  if (/<div>Kod terytorialny/) { $Teryt = next_line(); }
          if (/<div>Numer obwodu/) { $IdO = next_line(); }
           if (/<div>Adres/) { $Addr = next_line();
             $IdDataFull = "$fileName;$Teryt;$IdO;$Addr";
             $IdData = "$fileName;$Teryt;$IdO";
             last;
          }
       }
   }
   if ($mode eq 'I') {
   }

   if (/Wyniki wyborów na Kandydatów/) {  $mode = 'C' }
   if (/ZESTAWIENIE WYNIKÓW/) {  $mode = 'S';
       while (<>) {
          chomp();

	  ## pobieranie informacji nt. komisji
	  ## pominięto kilkanaście wierszy postaci:
	  ## if (/<div>###/) { $xxx = next_line() }
	  ## ...
          if (/<div>Liczba kart ważnych/) { $N_karty_wazne = next_line(); }
          if (/<div>Liczba głosów ważnych oddanych/) {
	    $N_glosy_wazne = next_line() ;
	    print X "$IdDataFull;$N_uprawnieni;$N_karty_otrzymane;$N_karty_niewykorzystane;"
	      . "$N_karty_wydane;$N_pelnomocnicy;$N_pakiety;$N_karty_wyjete;$karty_z_kopert;"
	      . "$N_karty_niewazne;$N_karty_wazne;$N_glosy_wazne;$N_glosy_niewazne\n";
	    last;
          }
       }

   ##########
   if (/Wyniki wyborów na listy/) {
     $mode = 'L' ;
     $colNo=0;
     %List = ();
     $start = 0;
     while (<>) {
          chomp();
          if (/<tbody>/) {$start = 1}
          if ($start == 1 ) {
              if (/<td[^<>]*>/ ) {
	         $colNo++;
                 $List{$colNo} = clean($_);
              }
              if (/<tr>/) {
                  $colNo=0;
                  %List = ();
		}
	      if (/<\/tr>/) {
		$line_ = "$IdData;";
		for $x (sort keys %List ) { $line_ .= "$List{$x};" }
		print L "$line_\n";
              }
              if (/<\/tbody>/ ) {###
                 last;
              } ##//
	    }
	}
   }
   ###########

   if ($mode eq 'C' && /<tr>/) {
       $colNo=0;
       %Candidate = ();
       while (<>) {
	 chomp();
	 
          if (/<table>/) { next } ## skip this line

	 if (/<\/tr>/ ) { 
              $line_ = "$IdData;";
              for $x (sort keys %Candidate ) {  $line_ .= "$Candidate{$x};" }
              print K "$line_\n";
              last; 
          } ## //end 
          if (/<td[^<>]*>/ ) { #############
	       $colNo++;
               $Candidate{$colNo} = clean($_);
	     }
	}
     }

}

### ### ### 

sub clean {
  my $x = shift;

  $x =~ s/<[^<>]+>//g;
  $x =~ s/^[\t ]+|[\t ]+$//g;
  $x =~ s/"//g;
  return ($x)
}


sub next_line {
   while (<>) {
      chomp();
      return (clean ($_));
   }
}

close(L);
close(K);
close(X);

print LOG "$fileName...\n";
close (LOG);

Kilka minut i po bólu. Teraz sprawdzam czy to co się pobrało i to co było do tej pory z grubsza się zgadza.

#!/usr/bin/perl
$pobranie1="komisje-frekwencja-ws2014.csv"; ## z 2015r
$pobranie2="ws2014_komisje.csv";

open(WX, $pobranie1) || die "cannot open $pobranie1\n";

while (<WX>) {
  chomp();
  ($teryt, $nrk, $nro, $adres, $lwug, $lkw, $lkwzu, 
        $lgnw, $lgw, $freq, $pgnw) = split /;/, $_;
  $LWUG1{"$teryt:$nro"} = $lwug; ## liczba wyborców
  $LGW1{"$teryt:$nro"} = $lgw; ## glosy ważne
  $ADDR1{"$teryt:$nro"} = $adres; ##
}
close (WX);

### ### ###

open(WY, $pobranie2) || die "cannot open $pobranie2\n";
while (<WY>) {
  chomp();
  ($id, $teryt, $idk, $adres, $uprawnieni, $kartyOtrzymane, 
    $kartyNiewydane, $kartyWydane, $pelnomocnicy, $pakiety, 
    $kartyWyjete, $koperty, $kartyNiewazne, $kartyWazne,
    $glosy, $glosyNiewazne) = split /;/, $_;
  $LWUG2{"$teryt:$idk"} = $uprawnieni;
  $LGW2{"$teryt:$idk"} = $glosy;
  $ADDR2{"$teryt:$idk"} = $adres;
}
close (WY);

### LWUG1 ma mniej głosów ## ### ### ### ###
for $ik ( sort keys %LWUG1 ) {
    if ( ( $LWUG1{$ik} != $LWUG2{$ik} ) || 
       ($LGW1{$ik} != $LGW2{$ik} )) {
       print "$ik $LWUG1{$ik} = $LWUG2{$ik} $LGW1{$ik} = $LGW2{$ik}\n";
    }
}

Identyfikatorem komisji na stronach PKW jest 6-cyfrowy numer TERYT + numer komisji (w gminie). Porównanie 26477 komisji pobranych 2015r. z 27446 komisjami pobranymi teraz (+969 komisji) daje w rezultacie:

021901:1 2020 = 2020 914 = 913
021901:2 2189 = 2189 742 = 741
026401:112 2039 = 2039 746 = 744
026401:17 2001 = 2001 536 = 534
026401:178 2073 = 2073 765 = 762
026401:18 1600 = 1600 474 = 473
026401:194 1615 = 1615 637 = 628
026401:215 1457 = 1457 528 = 527
026401:245 2058 = 2058 695 = 697
026401:42 1892 = 1892 504 = 503
026401:70 1823 = 1823 597 = 593
026401:78 1918 = 1918 762 = 760
241004:4 994 =  850 350 = 350
241005:13 1736 = 1736 764 = 762
241005:22 1422 = 1422 569 = 567
241005:6 1441 = 1441 732 = 723
241005:7 1668 = 1668 623 = 621

Czyli dane nie były picowane :-) Dobrze wiedzieć

Pobrane dane są tutaj.

poniedziałek, 17 września 2018

Wkurwiający problem kodowania UTF w Perlu

Z jakiś powodów obsługi przez Perla UTFa nie może być bezszmerowa. Zawsze coś nie działa i zawsze jest problem. I zawsze jest kombinowanie co by tu wstawić za zaklęcia żeby działało. Np. to zwykle działa:

#!/usb/bin/perl
use locale;
use utf8;
binmode(STDOUT, ":utf8");
##use open ":encoding(utf8)";
use open IN => ":encoding(utf8)", OUT => ":utf8";

albo to poniżej też czasami działa (wtedy kiedy powyższe nie działa):

use utf8;
binmode(STDOUT, ":utf8");
use open ":encoding(utf8)";

Czasami nawet nie potrzeba ostatniego use open ":encoding(utf8)";. Czemu nie wiem. Nadmiarowe polecenia psują kodowanie BTW (jakby ktoś myślał, że jak wstawi wszystkie polecenia, które dotyczą kodowania UTF ,,na zapas'' to będzie zawsze dobrze.)

Wyświetlanie śladów GPX (jest życie bez GoogleMaps)

Mój sposób na wyświetlanie na mapie danych w formacie GPX do tej pory polegał na uruchomieniu skryptu w PHP, który to skrypt pobierał nazwę pliku GPX, a następnie wypisywał stosowny plik HTML. W związku ze zmianą licencji przez Google, skypt przestał działać. Zmiana na OSM (Open Street Map) okazała się banalnie prosta:

<html>
<head>
  <title>GPX view facility</title>
  <link rel="stylesheet" href="/leaflet/leaflet.css" />
  <script src="/leaflet/leaflet.js"></script>
  <script src="/leaflet/gpx.js"></script>
  <style> #map { width: 960px; height:500px; } </style>
</head>
<body>
<div id="map"></div>
<script>

    var map = L.map('map',{
    center: [54.4, 18.4],
    zoom: 11
    });

    L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(map);

    <?
    $trasa = $_GET['trasa'];
    if ($trasa != '')  { print "var gpx = 'http://pinkaccordions.homelinux.org/Geo/gpx/$trasa.xml'"; }
   ?>

    new L.GPX(gpx, {async: true}).on('loaded', function(e) {
    map.fitBounds(e.target.getBounds());
    }).addTo(map);
</script>
</body>

Żeby powyższe działało trzeba pobrać i skopiować do właściwych katalogów: leaflet oraz plugin leaflet-gpx. Że działa można sprawdzić tutaj.

piątek, 14 września 2018

Wybory 2014 (revisited)

https://raw.githubusercontent.com/hrpunio/MBlog/master/pic/pgnw_correlations-0.png
pgnw vs PSL
https://raw.githubusercontent.com/hrpunio/MBlog/master/pic/pgnw_correlations-1.png
pgnw vs PiS
https://raw.githubusercontent.com/hrpunio/MBlog/master/pic/pgnw_correlations-2.png
pgnw vs PO

Że się zbliżają wybory samorządowe, to ja znowu pochyliłem się nad wynikami z poprzednich tj. z roku 2014. Piszę znowu, bo dane pobrałem dawno temu ze strony http://wybory2014.pkw.gov.pl/. Przypomnę też, że wybory te zakończyły się nielichym skandalem. Po pierwsze system informatyczny Państwowej Komisji Wyborczej zawiódł spektakularnie. Po drugie, nie tylko tradycyjnie odnotowano niską frekwencję, ale dodatkowo i z niewiadomych do końca powodów, doszła niesłychanie wysoka liczba oddanych głosów nieważnych. Po trzecie dramatyczna różnica pomiędzy wynikiem prognozy exit pool, a wynikiem oficjalnym spowodowała, że ówczesna opozycja oskarżyła ówczesnych rządzących o fałszerstwo wyborcze. Różnica sama w sobie nie jest oczywiście czymś niemożliwym, ale też prognozy exit pool są no raczej na tyle dokładne, że na ich podstawie jedni uznają się za wygranych, a inni za przegranych w tzw. cywilizowanym świecie. A w PL akurat ktoś się rąbnął o 50%.

BTW wyobraźmy sobie reakcję #SektyPancernejKonsytytucji (aka #OpozycjiTotalnej) na coś takiego dziś.

Wracając do bazy protokołów. Jest ona niekompletna, co było stanem na czas po wyborach kiedy była pobierana i co (według mnie) było spowodowane przez system informatyczny PKW (czytaj chaos w PKW). Teraz widzę, że baza na stronie PKW wygląda inaczej i być może jest kompletna, ale nie chce mi się tego (na razie) jeszcze raz pobierać. Moja baza jest oryginalna, a nie picowana (żart :-)), a zawiera ponad 96% tego co powinna zawierać (zakładając, że obwodów jest 27435 ja mam 26495). Ta baza jest dostępna tutaj.

Mówiąc konkretnie i porównując z listą 27435 obwodów braki są następujące: Dolnośląskie = 38; Kujawsko-Pomorskie = 17; Lubelskie = 14; Lubuskie = 12; Łódzkie = 14; Małopolskie = 22; Mazowieckie = 1139; Opolskie = 7; Podkarpackie = 10; Podlaskie = 5; Pomorskie = 20; Śląskie = 28; Świętokrzyskie = 13; Warmińsko-Mazurskie = 12; Wielkopolskie = 14; Zachodniopomorskie = 18. Zatem baza jest w miarę kompletna (za wyjątkiem woj. Mazowieckiego, w przypadku którego protokoły nie były opublikowane nawet kilka miesięcy po wyborach).

Każdy protokół zawiera adres i kod teryt komisji obwodowej, tyle że TERYT jest 6 cyfrowy, a nie pełny. Z tego powodu klasyfikację miasto/wieś dokonałem w taki sposób że gmina jest `miejska' jeżeli wg klasyfikacji teryt ma ona typ `gmina miejska' (U) a w każdym innym przypadku (miejsko-wiejska, wiejska, miasto w gminie miejsko-wiejskiej albo obszar wiejski w gminie miejsko-wiejskiej) gmina jest `wiejska' (R). Jest 9996 gmin typu U, a 16881 gmin jest typu R.

Na początek wykonałem prostą analizę eksploracyjną licząc wartości średnie, korelacje oraz regresje pomiędzy głosami nieważnymi a poparciem dla partii. Stosowny fragment R-skryptu wygląda następująco:

## Korelacje pomiędzy % głosów a % głosów niewaznych
cor(d$pgnw14, d$pslp, use = "complete")

## Wykresy rozrzutu  ## ###
lm <- lm(data=d, pslp ~ pgnw14 ); summary(lm)
lmc <- coef(lm);
title <- sprintf ("psl = %.2f pgnw + %.1f", lmc[2], lmc[1] );

ggplot(d, aes(x = pgnw14, y=pslp )) +
  geom_point(colour = 'blue') +
  ggtitle(title) +
  theme(plot.title = element_text(hjust = 0.5)) +
  xlab(label="pgnw") +
  ylab(label="pslp") +
  geom_smooth(method = "lm", colour = 'black')

lm <- lm(data=d, pisp ~ pgnw14 ); summary(lm)
https://raw.githubusercontent.com/hrpunio/MBlog/master/pic/mapa-pgnw0.png
pgnw
https://raw.githubusercontent.com/hrpunio/MBlog/master/pic/mapa-pgnw1.png
pgnw vs psl
https://raw.githubusercontent.com/hrpunio/MBlog/master/pic/mapa-pgnw2.png
pgnw vs pis
https://raw.githubusercontent.com/hrpunio/MBlog/master/pic/mapa-pgnw3.png
pgnw vs po

Wynik są następujące:

  ## pgnw (procent głosów nieważnych)
  Min. 1st Qu.  Median    Mean 3rd Qu.    Max.  Grupa
  0.00    8.20   11.67   12.82   16.05   56.41  Razem
  0.00   12.55   18.18   18.75   23.98  100.00  Miasto
  0.00   17.05   21.37   22.15   26.38   77.42  Wieś
  ## poparcie
  ## Miasto
  0.00   6.719   10.12   13.82   16.53  100.00  PSL
  0.00   20.83   25.91   27.12   32.35  100.00  PiS
  0.00   25.20   32.56   32.90   39.84   85.00  PO
  ## Wieś
  0.00   20.11   32.61   35.86   49.27  100.00  PSL
  0.00   15.42   22.60   25.55   32.96  100.00  PiS
  0.00   7.748   15.43   18.53   26.44   92.65  PO
  ## wsp. korelacji (pgnw vs poparcie)
  ## PSL             PiS             PO         Grupa
  0.4053339      -0.1972364      -0.3321558     Razem
  0.4333851      -0.2104114      -0.2648886     Miasto
  0.0905243      -0.1931745      -0.0370197     Wieś

Liczba głosów nieważnych była wyższa na obszarach wiejskich (średnia 22,15% vs 18,75%). Poparcie dla czołowych partii był na wsi najwyższe dla PSL, potem PiS a na końcu PO; w mieście dokładnie odwrotnie. Wystąpiła dodatnia korelacja pomiędzy liczbą głosów nieważnych, a poparciem w przypadku PSL. Nieoczekiwanie była większa na obszarach większych miast, a mniejsza poza nimi. W przypadku zarówno PiS jak i PO korelacja była ujemna (większy udział głosów nieważnych oznacza mniejsze poparcie). Zależność pomiędzy liczbą głosów nieważnych a poparciem ilustrują także wykresy.

Jest zatem różnica między `miastem' a `wsią'. A czy jest różnica w decyzjach w aspekcie przestrzennym? Obliczyłem średnią wartość współczynnika korelacji pomiędzy liczbą głosów nieważnych, a poparciem w powiatach:

powiat <- substr(d$teryt, 0, 4)
d[,"powiat"] <- powiat;

p.psl <- d %>% group_by(powiat) %>% summarise(V1=cor(pgnw14,pslp))
p.pis <- d %>% group_by(powiat) %>% summarise(V1=cor(pgnw14,pis))
p.po  <- d %>% group_by(powiat) %>% summarise(V1=cor(pgnw14,po))

print(p.psl, n=Inf)
print(p.pis, n=Inf)
print(p.po, n=Inf)

> fivenum(p.psl$V1)
[1] -0.5984602  0.1066262  0.2906827  0.4491453  0.8536293
> fivenum(p.pis$V1)
[1] -0.7985236 -0.4216242 -0.2965959 -0.1658306  0.1877184
> fivenum(p.po$V1)
[1] -0.8092580 -0.4891280 -0.3725242 -0.2420753  0.4726305

Jak widać są znaczące różnice...

Google Fusion Tables (GFT)

Jedyne narzędzie jakie znam/mam/używam do przestrzennej wizualizacji danych.

Protokoły komisji zawierają adresy. Wykonałem geokodowanie tychże adresów za pomocą geocodera Google. Z różnym skutkiem, mianowicie 27435 komisji zgeokodowało się na 21716 różnych adresów. Zdarza się faktycznie, że dwie (a nawet więcej) komisje mają siedzibę w tym samym budynku. Nie mając ani chęci ani czasu na dokładną inspekcję sprawdziłem jak wygląda rozkład siedzib/adresów względem liczby komisji:

perl chk_duplicated_coords.pl | sort  -n
...
15 49.9062558 21.7658112
16 51.663189 16.5125886
18 51.2070067 16.1553231
20 49.9953359 21.3075494
28 50.5798603 21.6925451
40 52.6483303 19.0677357
50 54.3520252 18.6466384

Pierwsza kolumna to liczba komisji. Można przyjąć że jeżeli liczba komisji jest większa od 4 to doszło do błędnego geokodowania. Takich wątpliwych adresów jest:

perl chk_duplicated_coords.pl | awk '$1 > 4 {print $0}' | wc -l
142  

Zostawiam ten problem na później przy czym z punktu widzenia wizualizacji za pomocą GFT, coś co ma identyczne współrzędne się nałoży na siebie, np. 50 komisji o współrzędnych 54.3520252/18.6466384 będzie pokazane na mapie jako jedna kropka (przy założeniu że zastosujemy kropkę do wizualizacji oczywiście). Żeby wszystkie komisje były widoczne (nawet te które mają prawidłowe ale identyczne współrzędne), to można zastosować losowe drganie (jitter). Tyle na razie.

Plik powiaty_korelacje_pgnw_poparcie.csv zawiera m.in. obliczone w R współczynniki korelacji pomiędzy liczbą głosów nieważnych, a poparciem. Mam też plik zawierający obrysy powiatów i ich środki (teryt_powiaty_BB.csv). Na pierwszej mapie przedstawiono przeciętne wartości pgnw (odsetek głosów nieważnych). Czerwone i niebieskie kropki oznaczają wysokie wartości pgnw. Wyraźnie widać, że powiaty na zachodzie / północnym zachodzie mają wyższe wartości pgnw niż w pozostałej częsci kraju. Takiej przestrzennej zależności nie widać dla trzech pozostałych mapek, ilustrujących przeciętną wielkość współczynnika korelacji pomiędzy poparciem dla partii (PSL, PiS, PO) a odsetkiem głosów nieważnych. Wniosek: sympatycy wszystkich partii mylili się podobnie, a ich błąd był korzystny dla PSL.

Dane, skrypty i reszta wykresów są tutaj. Mapy GFT: poparcie/pgnw/powiaty oraz pgnw/obwody.

niedziela, 9 września 2018

Kociewie Kołem 2018 (how it unfolded)

Z Elką wyjechaliśmy 6:10 albo coś w tym stylu (plan był że o 6:00)

Po z grubsza godzinie byliśmy na tym Owidz-Grodzisku...

Poleciałem po numer i 7:40 byłem gotowy. Elka odjechała. Na start podjechałem 7:50 a tam tłumów nie ma; ostatecznie wystartowałem o 8:06 z pierwszą grupą.

Plan był taki żeby zapierdzielać w grupie dopóki się da, ale na bufetach stawać i jechać z następną grupą. W tym zbożnym celu nie wziąłem prawie nic do jedzenia (ostatecznie za start zapłaciłem 111 PLN, więc niech się chociaż trochę zwróci). Ponieważ dobrze mi szło i ponieważ pierwszy bufet był już na 40 km, to go ominąłem. Być może to był błąd, bo tak do 70 km to mi szło, a potem już jakby nie do końca. Do 80 km jeszcze się trzymałem, ale do bufetu #2 (na prawie 100 km) dotarłem w kiepskim stanie i za grupą. W bufecie szandar i ciasta, przy czym szandar, to zapieczone utarte ziemniaki z cebulą i boczkiem. Rodzaj mega-placka ziemniaczanego (przepis w goole można znaleźć). Jem tego 2/3 porcji, resztę w kieszeń na spróbowanie dla Elki. Do szandara kawka + mały serniczek i jadę dalej. BTW mi ten szandar smakował, ale opinia może być nieobiektywna, bo głodny byłem.

Część grupy, z którą jechałem bufetowała tak długo, że mogę kontynuować jazdę w mocnym towarzystwie. Całkiem nieźle mi znowu idzie, co z jednej strony pewnie zasługą szandara, a z drugiej że grupa ciut wolniej pomyka, bo jednak najsilniejszych już w niej nie ma. Na 115 km bufetu #3. Ja skręcam do bufetu, a moja grupa nie. Na bufecie tłumy, bo tą część trasy pokonują już uczestnicy, którzy się zapisali na krótsze dystanse. Zamiast szandara dają racuchy i jakąś zupę z kapustą. Za zupę dziękuję, jem dwa racuchy (dwa następne biorę na spróbowanie dla Elki) z kawką i dalej.

Teraz jadę w sumie sam, mijając pojedynczych maruderów. Wreszcie dogania mnie poważna grupa i następne parę kilometrów mam solidne koło. Tylko parę, bo bufet #4 jeszcze został (130 km). Moja grupa jedzie dalej a ja skręcam. Dobra decyzja, bo bufet #4 najlepiej zaopatrzony. Wprawdzie bardziej oglądam niż jem, ale nawet dla popatrzenia warto było stanąć. Są omasty w tuzinie bodajże wariantów (z nieśmiertelnym smalcem na czele, ale zmieszanym z grzybami), ciasta, jogurty... Ja decyduję się na kaszę manną z czarną jagodą + dwie małe porcje jogurtu. Kasza tak mi smakuje, że dwie porcje ładuję do bidonu dla Elki (w domu się dowiaduję, że Elka nie lubi kaszy mannej.)

Od bufetu #4 do mety mam 25km. Z 10 km jadę ze starszym gościem, resztę sam. Dojeżdżam do mety o 13:20 czy jakoś tak czyli po 5h z niewielkim ogonkiem. Trasa co mi się wydawała na rysunku mocno sfalowana okazała się całkiem płaska. Jedyna niewielka dolegliwość to stan dróg, nie tyle dziurawych co o nierównej nawierzchni (pofalowany/popękany asfalt)

Idę po medal, potem po makaron. Potem jadę 30 km do Tczewa na pociąg :-). Do Pelplina jest bliżej, ale tam najbliższy pociąg do Gdańska odjeżdża o 16:45.

Żeby się nie stresować, nie sprawdzam połączeń z Trójmiastem z Tczewa do którego docieram o 15:15. Pociąg mam 15:17 i już na niego nie zdążę. Następny jest o 16:30. Pech...

W domu jestem o 17:40.

Sprawy sprzętowe

Eksperymentalnie dokleiłem do mostka powerbank (Anker Mini 3000 mAh) do zasilania kamery, która normalnie działa circa 2h. Alternatywą byłoby wymienianie akumulatora na bufetach, ale to zawsze stres i kłopot, bo trzeba odkręcić śrubę mocującą, wyjąć kamerę z obudowy a potem wsadzić i zakręcić. U mnie nie jest to aż tak trywialne z uwagi na konstrukcję obudowy i sposób jej umieszczenia (pod kierownicą, bo przecież nie będą jeździł z obciachowo sterczącą kamerą.) Pomysł z powerbankiem się sprawdził, a kamera się wyłączyła no dokładnie na linii mety (czasami ma się szczęście.) Teraz mam 128Gb do przetworzenia...

Ślad jest tutaj (albo kml.) Kilka zdjęć jest tutaj.