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.

czwartek, 6 września 2018

Przygotowania do Kociewie Kołem

W zeszłym roku wziąłem udział w imprezie kolarsko-rekreacyjnej pn. Żuławy w Koło, a teraz zapisałem się na Kociewie Kołem, która ma się odbyć 9 września. Ta sama firma organizuje jak się łatwo domyśleć.

Żeby nie jechać w ciemno pobrałem stosowne dane ze strony organizatora, zamieniłem je na plik CSV i policzyłem różne statystyki. W 2016 średnia prędkość na najdłuższym dystancie (170 km) wyniosła na przykład 27,05 km/h. Rok później (dystans 155 km) było to 26,69 km/h. Czyli sporo, bo na płaskiej i krótszej trasie Żuławy w Koło było dla przykładu w 2016 roku 25,47 km/h, a w 2017 26,23 km/h. Więcej szczegółów na wykresach pudełkowych obok.

Ściągnąłem też w środę listę uczestników, których okazało się jest 719, w tym z Gdańska 332, z Gdyni 107, a tak w ogóle to ze 120 różnych miejscowości. Za pomocą Google Fusion Tables można pokazać listę na mapie. Żeby kropki z tej samej miejscowości się nie nakładały na siebie zastosowałem losowe `drganie' (jitter) wg. algorytmu:

### Jitter w kole o średnicy $r
$factorJ = 0.00001; ## ustalone heurystycznie

$sd = sqrt($factorJ * $N); # $N liczba kropek dla miejscowosci, tj dla GDA 332
$r = $sd * sqrt(rand()); $theta = rand() * 2 * $pi;
$rand_lat = $lat + $r * cos($theta);
$rand_lon = $lon + $r * sin($theta);

### Jitter w prostokącie o boku $r
$rand_lat = $lat + rand($sd);
$rand_lon = $lon + rand($sd);

Rezultat jak na obrazku poniżej, albo tutaj.

Lewy obrazek to mapa bez `jittera' a prawy z zastosowanym `jitterem'.

Google Maps API przestało działać

Bo zmieniła się licencja na korzystanie (z Google Maps API):

Google has made significant changes to the way they allow the use of their Google Maps Platform. Google maintains its Google Map API will still be free to a certain limit and it provides free $200 monthly recurring credit to every user. Google requires all user to have a billing account. They must be willing to submit credit card details, so excess is charged pro rata.

Więcej jest tutaj.

W rezultacie tych zmian na mapach Google, które wykorzystują poprzez API (konkretnie korzystają z Maps JS API) pojawiło się okienko z komunikatem Ta strona nie może poprawnie wczytać Map Google. Sama wyświetlona mapa jest zaś na szaro i ma powtórzony znak wodny For development purposes only.

No kicha niewątpliwie. Na razie nie wiem co robić, bo rejestrować kartę do moich hobbystycznych projektów to mi się nie chce. Rozważam wykorzystanie czegoś w zamian.

Oprócz Google Maps JS API korzystałem też z Google Geocoding API. No i ta usługa też przestała działać: OVER_QUERY_LIMIT dostaję w odpowiedzi. Tutaj też rozważam wykorzystanie czegoś w zamian, a nawet rozważyłem i spróbowałem: darmowy serwis MapQuest. BTW nie wiemy czy to jest najlepszy zamiennik ale spróbować trzeba.

Piszą (cf. https://developer.mapquest.com/documentation/open/geocoding-api/), że: The Open Geocoding API is similar to our MapQuest Geocoding API, but instead relies solely on data contributed to OpenStreetMap. Zapytania mogą mieć postać metod GET lub POST. Jest jeszcze coś co się nazywa Batch Geocode, które to coś pozwala na geokodowania do 100 adresów na raz. Szczegółowa dokumentacja jest tutaj.

Posługując się metodą GET korzysta się bardzo prosto:

http://open.mapquestapi.com/geocoding/v1/address?key=APIKEY&location=ADDRESS

Użyteczne parametry: boundingBox=UppLLat,UppLLon,LowRLat,LowRLon (górny lewy/dolny prawy), maxResults, outFormat (json,xml albo csv).

Przykłady:

http://open.mapquestapi.com/geocoding/v1/address?key=KLUCZ&location=Sopot,PL&maxResults=10
## BB województwa pomorskiego 54.83572969999 19.6489837 53.49067179999999 16.699129
http://open.mapquestapi.com/geocoding/v1/address?key=KLUCZ&location=Sopot,PL&\
  boundingBox=54.835729,19.648983,53.490671,16.699129

Żeby było łatwiej powyższe zaimplementowałem w prostym skrypcie Perlowym:

#!/usr/bin/perl
#
use strict;
use LWP::Simple; # from CPAN
use JSON qw( decode_json ); # from CPAN
use Getopt::Long;
#use Encode;

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

my $format = "json"; # xml  | csv (not implemented)
my $myAPIkey = 'APIKEY'; ## Klucz od MapQuesta (trzeba się zarejestrować)
my $geocodeapi = "http://open.mapquestapi.com/geocoding/v1/address?key=$myAPIkey&location=";
my $addrLine = '';
my $logFile = '';
my $boundingBox = '';
my $country = 'PL';
my $maxResults = 1; ## podaj tylko pierwszy

my $USAGE="USAGE: $0 [-a ADDRESS] [-log FILENAME] [-country CODE] [-bb SWlat,SWlng|NElat,NElng] \n";

GetOptions( "a=s" => \$addrLine, "log=s" => \$logFile, "country=s" => \$country, 
    "bb=s" => \$boundingBox,  "max=i" => \$maxResults ) ;

if ($logFile) { open LOG, ">>$logFile" || die "Cannot log to $logFile\n" ;
 print STDERR "*** Logging JSON to $logFile ***\n" ; } else {
 print STDERR "*** Logging JSON OFF ***\n"; }

unless ($addrLine ) { print STDERR "$USAGE"; exit 0; }

my ($lat, $lng, $quality, $lname) = getLatLong($addrLine, $boundingBox);

printf "Lat/Lng/Name/Quality: %s %s %s %s\n", $lat, $lng, $lname, $quality;

if ($logFile) { close (LOG) ; }

### ### ### ### ### ### ### ###
sub getLatLong($){
  my $address = shift;
  my $bb = shift;

  my $url = $geocodeapi . "$address,$country" ; #
  if ($boundingBox ) { $bb =~ s/[\|,]/,/g; $url .= "&boundingBox=$bb" ; }
  if ($maxResults ) { $url .= "&maxResults=$maxResults" ; }

  print STDERR "\n*** [URL: $url] ***\n";

  my $json = get($url);
  if ($logFile) { print LOG "##_comment_:\n##_comment_:$url\n$json\n"; }

  my $d_json = decode_json( $json );

  #if ( $d_json->{statuscode} eq '0' ) {
  my $loc_name =  $d_json->{results}->[0]->{providedLocation}->{location};
  my $lat = $d_json->{results}->[0]->{locations}->[0]->{latLng}->{lat};
  my $lng = $d_json->{results}->[0]->{locations}->[0]->{latLng}->{lng};
  my $quality = $d_json->{results}->[0]->{locations}->[0]->{geocodeQuality};

  return ($lat, $lng, $quality, $loc_name );
  #} else { return ( $d_json->{statuscode} ) }
} ## ///

Teraz wystarczy na przykład:

geocodeCoder1.pl -a Sopot -bb 54.835729,19.648983,53.490671,16.6991

czwartek, 30 sierpnia 2018

Rysowanie profilu wysokości w R

Ze śladu GPX prostym skryptem wyciągam co trzeba tworząc plik CSV o następującej zawartości (nazwy kolumn: data-czas,wysokość,prędkość,dystans przebyty):

daytime;ele;speed;dist  

Teraz poniższym skryptem rysuję profile wysokości (wysokość/prędkość vs czas oraz wysokość/prędkość vs dystans)

library(reshape)
require(ggplot2)

graphWd <- 6
graphHt <- 5

args = commandArgs(trailingOnly = TRUE);

if (length(args)==0) { stop("Podaj nazwę pliku CSV", call.=FALSE) }

fileBase <- gsub(".csv", "", args[1]);
outFile1 <- paste (fileBase, "_1.pdf", sep = "");
outFile2 <- paste (fileBase, "_2.pdf", sep = "");

what <- args[2];

# http://stackoverflow.com/questions/7381455/filtering-a-data-frame-by-values-in-a-column
d <- read.csv(args[1], sep = ';',  header=T, na.string="NA");
coeff <- median(d$ele)/median(d$speed)
d$speed <- d$speed * coeff


p1 <- ggplot(d, aes(x = as.POSIXct(daytime, format="%Y-%m-%dT%H:%M:%SZ"))) +
  geom_line(aes(y = ele, colour = 'wysokość', group = 1), size=1.5) +
  geom_line(aes(y = speed, colour = 'prędkość', group = 1), size=.5) +
  stat_smooth(aes(y=speed, x=as.POSIXct(daytime, format="%Y-%m-%dT%H:%M:%SZ"), colour ='prędkość wygładzona')) +
  ylab(label="Wysokość [mnpm]") +
  xlab(label="czas") +
  scale_y_continuous( sec.axis = sec_axis(name="Prędkość [kmh]",  ~./ coeff)) +
  labs(colour = paste( what )) +
  theme(legend.position="top") +
  theme(legend.text=element_text(size=12));
p1
ggsave(file=outFile1, width=graphWd, height=graphHt )

p2 <- ggplot(d, aes(x = dist)) +
  geom_line(aes(y = ele, colour = 'wysokość', group = 1), size=1.5) +
  geom_line(aes(y = speed, colour = 'prędkość', group = 1), size=.5) +
  ##geom_smooth() +
  stat_smooth(aes(y=speed, x=dist, colour ='prędkość wygładzona')) +
  ylab(label="Wysokość [mnpm]") +
  xlab(label="dystans") +
  scale_y_continuous( sec.axis = sec_axis(name="Prędkość [kmh]",  ~./ coeff)) +
  labs(colour = paste( what )) +
  theme(legend.position="top") +
  theme(legend.text=element_text(size=12));
p2

ps <- stat_smooth(aes(y=speed, x=dist));

ggsave(file=outFile2, width=graphWd, height=graphHt )

Teraz na koniec ciekawostka. Mój smartfon produkuje pliki GPX z superdokładnym stemplem czasu np. 2018-08-23T04:52:43.168Z, na czym wysypuje się R. Po prostu usuwam część po kropce dziesiętnej oraz samą kropkę (tj. .168Z) i działa.

Wycieczka do Gruzji #4

Pierwszy raport (może będzie później bardziej szczegółowy)...

Dojazd 18--19.08

Wyjazd 8:20 z Sopotu na Lotnisko Katowice-Pyrzowice. Po drodze przystanek w Częstochowie w lokalu Bistro-Setka (polecamy). Samochód został na parkingu Wczasowicz (też polecamy).

Start krótko po 17:00 Lądowanie w Kutaisi około 22:00 (różnica czasu). Od razu lecimy po gruzińską kartę SIM. Mamy wprawdzie gruzińskie SIMy z poprzedniej wycieczki, ale akurat nie ma tej konkretnej firmy w Kutaisi na lotnisku (karta była kupowana w Tbilisi). Ponieważ jest jedenasta w nocy, ponieważ rano pojedziemy na zadupie gdzie w ogóle nic przypuszczalnie nie załatwimy i ponieważ karta kosztuje zaledwie kilka lari kupujemy nowe. Procedura jest szybka i sprawna tyle, że moja karta nie działa. Nie było czasu na reklamacje, ważniejsze było dostanie się do Kutaisi więc problem odpuściłem. Kupiliśmy bilety na marszrutkę i pojechaliśmy do miasta. Po drodze dołączyliśmy do dwójki dziewczyn z PL, które miały rezerwację w hostelu. One miały, my nie ale też nas przenocowali za 15 GEL/osobę. Do tego zamówili taksówkę na rano na dworzec autobusowy skąd odchodzą marszrutki do Mestii. Bilet do Mestii kosztuje 25 lari. Odjazd o 8:00.

Po dotarciu do Mestii spotykamy się z naszym przewodnikiem, który wiezie nas na kwaterę. Mówiąc całkiem szczerze to kupiliśmy kota w worku. Zabrałem się bowiem za organizowanie naszego trekingu na tyle późno, że przewodnika wynajeliśmy w klasycznej strategii rozpoznania walką. Po wpisaniu w google trekking Mestia Ushguli, wysłałem mejla do firmy, której strona/opis mi się spodobała. Firma odpisała że jak najbardziej a nawet w terminie 20--23 będzie przewodnik mówiący po polsku. OK, wchodzimy w to. Teraz w Mestii poznajemy w co...

Więc polskojęzyczny przewodnik nazywa się Agnieszka i Lasza, polsko-gruzińskie małżeństwo prowadzące firmę pn. GeoPol travel (są na FB). Nas poprowadzi Agnieszka (pierwszy dzień z mężem). W kontrakcie mamy też wyżywienie, co w praktyce oznacza, że każdy guesthouse serwuje nam śniadanie i kolację oraz wręcza launchbox do zjedzenia na trasie. Jedzenie nieprzetworzone: chleb, ser, warzywa... Samo zdrowie...

Rozpakowujemy się. Popołudnie czas wolny, trekking rozpoczynamy jutro. Zwiedzamy Mestię, w tym muzeum oraz wieżę do której można wejść. Po powrocie z miasta okazuje się, że mamy towarzystwo w hostelu: dokwaterowała się wycieczka z Izraela (ok 10 os osób--nie liczyliśmy dokładnie)

dzień #1: 20.08 Mestia-Zabeshi (17,0 km na moim GPS)

Rano śniadanie o 8:00. Wycieczka z Izraela je wcześniej i wcześniej wychodzi na tą samą trasę co my (wkrótce ich miniemy bo wolno chodzą). Ponieważ wynajęliśmy przewodnika trekking przebiega bezstresowo. Idziemy tam gdzie każą i podziwimy widoki po drodze. Atrakcją są noclegi, będące okazją do poznania ludzi dosłownie z całego świata. Pierwszy nocleg mamy w guesthausie Beqa Naveriani (Beka to popularne imię męskie tutaj). Na kwaterze jesteśmy my i 6 Niemców + ich przewodnik (których nb. już poznaliśmy na trasie). Niemcy (starsi od nas) idą bez bagaży, które wiezie wynajęty koń powożony przez wynajętego człowieka. Można wynająć samochód, bo do wiosek idzie dojechać drogą, ale podobno koń jest tańszy. Wspólną kolację zakłóca wyłączenie prądu (do rana). Trochę siedzimy przy świecach, ale w końcu idziemy spać. Wstaję rano i prądu dalej nie ma. Nie ma też w związku z tym wody w kranach i nie tylko (jak u Kazika S.: wszystkie deski zasikane/wszystkie kible zasrane/Mars napada) Rano podczas śniadania włączają prąd.

dzień #2: 21.08 Zabeshi-Adishi (11,6 km)

Śniadanie o 8:00. Po drodze zbieramy grzyby, które Agnieszka przygotuje na kolację. Nocujemy (guesthouse Bedo&Tamila jeżeli dobrze odczytałem nazwę) w składzie: 2 Hindusów, Hiszpan (wszyscy Cambridge/fizyka) Węgierka + Francuz mieszkający w Budapeszcie, Żydówka z Izraela (polskie korzenie) oraz dwóch Niemców z Monachium, pokonujących szlak na rowerach downhillowych (jeden z Polskim nazwiskiem, ale nic poza tym). Z tym downhillem to dziwaczny pomysł, ja bym nie rekomendował...

dzień #3: 22.08 Adishi-Iprali (18,5 km)

Dzień najdłuższy na całej wycieczce. Urozmaiceniem jest przejazd przez rzekę na koniu (z braku mostu). Można przejść, ale wtedy trzeba mieć jakieś inne obuwie no i zdejmować buty. Po drodze do Iprali mijamy pozostałości wioski Khalde Nocujemy w Ucha guesthouse, w którym nocuje chyba połowa tych co idą szlakiem do Iprali i nie chcą spać w namiotach:-)

dzień #4: 23.08 Iprali-Ushguli (16,1 km)

W zasadzie koniec wielkiego trekkingu. Rano jedziemy do Uszguli samochodem. Tam idziemy oglądać lodowiec, po powrocie zwiedzamy Uszguli. Około 16:00 powrót samochodem do Uszguli (2 godziny, bo droga jest w budowie) W Uszguli/Mestii jest masa rowerzystów na rowerach MTB. NB: byłem już 3 razy w Gruzji i praktycznie nie widziałem rowerzystów, a teraz całe stada--miejscowi (głównie dzieci), turyści. Widziałem nawet porządny sklep w Kutaisi i masę rowerów na targu (tureckim) tamże. Nie wiem czy to ,,efekt Swanetii'' czy też rowery stały się bardziej popularne w całej Gruzji.

dzień #5: 24.08 Mestia (ok. 20km)

Zostajemy jeden dzień dłużej w Mestii i idziemy oficjalnym szlakiem na punkt widokowy Zuruldi. Trasa taka sobie, bo połowa wiedzie wzdłuż drogi asfaltowej. Nie dochodzimy do Zuruldi tylko do Heshkili huts. Tam spotykamy wycieczkę młodych Gruzinek. Jedna przyznaje się do Polskiego pochodzenia (babka Różycka). To już trzecia osoba przyznająca się do Polskiego przodka BTW (Żydówka/Adishi, Angielka/Iprali). Wracamy tą samą drogą.

Powrót

Sumując przeszliśmy ok 63,0km + 20km ostatniego dnia idąc na Zuruldi (ale nie dochodząc tam)...

Odjazd z Mestii teoretycznie 8.00 Teoretycznie bo przez circa 30 minut busik krążył po mieście w poszukiwaniu pasażerów, których ciągle brakowało do kompletu. W końcu zdesperowany kierowca zajechał na stację benzynową na rogatkach miasta, gdzie zarządził przesiadkę do innego busa. Teraz już był prawie komplet, tyle że to nie był koniec kombinacji. Po jakieś pół godzinie zjeżdżania serpentynami z Mesti do Zugdidi pojawił się nieoczekiwanie pierwszy bus z jednym pasażerem w środku--który później okazał się zmiennikiem kierowcy a z pobliskiej chałupy wyłonił się tłum 9 Gruzinów, ewidentnie kandydatów na wakujące 5 miejsc. Kurcze co teraz...

Szczęśliwie z tej dziewiątki, troje było żegnających, więc nie było aż tak wielkich problemów z upchaniem reszty. Papierosek, buzi-buzi i jedziemy. Nawet nam idzie i doganiamy całe stado marszrutek, które robią sobie przerwę w no-name miejscu przed Zugdidi. Niestety nasi kierowcy też tu śniadaniują potem palą, co w rezultacie skutkuje następnymi 30 minutami w plecy. Jest 10:30, jechaliśmy może 1,5 godziny reszta to przerwy. No ale teraz bus rwie w dół i jest nadzieja. Całkiem sprawnie mijamy Zugdidi, zjeżdżamy do stacji benzynowej. Przerwa. Idziemy do sklepu, wracamy a samochód właśnie odjechał chuj-wi-gdzie. Współpasażer z Ukrainy oznajmia, że celem wymiany koła. Siedzimy czekamy. Bus wraca po 20min. Jedziemy dalej ale nie za długo bo bus zjeżdża do pierwszej przydrożnej wulkanizacji. Coś jednak nie gra, ale widać nie mają tego co trzeba bo stoimy zaledwie 5 minut i jedziemy do następnej przydrożnej wulkanizatorni, a potem do jeszcze następnej. Tam chyba mają. Chyba bo nie jedziemy dalej, ale też nic się nie dzieje. Kierowcy poszli do kanciapy wulkanizatora i widocznie na coś czekają. Po 20 minutach wreszcie pojawia się podnośnik i nowe (pardon nowsze koło). 2 minuty roboty i możemy jechać dalej... Ciekawe czemu służyły te 20 minut przygotowań... Jesteśmy zdrowo spóźnieni docierając około 15:00 do Kutaisi. Wysiadamy życząc współpasażerom bezawaryjnej dalszej jazdy do Tbilisi, do której dotrą -- w razie spełnienia się naszych życzeń -- po następnych 4h czyli około 19:00 (11 godzin w busie celem przejechania około 450km)

Różne rzeczy

Olympus OMD/EM10 + Sony RX100M3. GDP pocket się sprawdził i warto go zabierać. Powerbanki okazały się niepotrzebne, ale chyba jednak warto je zabierać. Pogoda Była rewelacyjna. W szczególności zero opadów.

Do pobrania ślad ze zdjęciami; ślad ze wszystkimi zdjęciami; zdjęcia; ślady gpx/kml.

piątek, 27 lipca 2018

Wycieczka do Lwowa 2018

Że Wizzair lata z GDA do Lwowa, to polecieliśmy na wycieczkę.

W poniedziałek 16 lipca o 6:50 polecieliśmy, lądując 1:30 później, tj. circa 9:15 we Lwowie. Ja w sobotę się zaprawiłem na rowerze na fest i wprawdzie w niedzielę było trochę lepiej, ale w poniedziałek dalej byłem cały zasmarkany, więc niespecjalnie mnie ucieszył rzęsisty deszcz na powitanie we Lwowie. Elka mówi, że prognozy są kiepskie i będzie padać cały tydzień. No masz załatwię się na amen...

Sprzed terminala pojechaliśmy trolejbusem do centrum. Nasza kwatera, wynajęta przez AirBNB jest na ulicy Szpitalnej. Pierwszy punkt wycieczki zatem, to dotrzeć na Szpitalną. Ciągle leje. Trolejbus dociera do centrum. Wysiadamy, w kiosku kupujemy kartę SIM (za circa 8PLN) i idziemy do kawiarni zamienić karty w moim Xiaomi. Internet działa na początku kiepsko (potem jest OK), ale ponieważ Szpitalna jest w pobliżu, to bez problemu znajdujemy kwaterę. Lokal jest OK.

Po zainstalowaniu się w kwaterze zwiedzamy stare miasto i wchodzimy na wzgórze pn Wysoki Zamek. Wracamy na kwaterę o 17:00.

Cmentarz Łyczkowski

Ponieważ pogoda w kolejnych dniach jest niepewna, to decydujemy się zwiedzić cmentarz Łyczakowski póki nie pada. Idziemy na cmentarz piechotą, żeby po drodze zwiedzić miasto (można tramwajem jechać). W rezultacie zwiedzanie plus dojście zajmuje nam pół dnia. Do tego ponad godzinę trwa konsumpcja obiadu, a to dlatego, że długo trzeba czekać na podanie (częste w restauracjach, które zwiedziliśmy; być może powodem jest sezon turystyczny). Po obiedzie jedziemy do miasteczka Żółkiew. Do Żółkwi jeżdżą autobusy z Północnego Dworca Autobusowego (ulica Bohdana Chmielnickiego 225). Ponieważ dworzec jest dość daleko od centrum, to pytamy się baby w kiosku czym dojechać. Mówi, że tramwajem nr 6 bodajże (zły pomysł, bo potem jeszcze trzeba kawałek podejść--podała po prostu numer tramwaju z najbliższego przystanku). Zwiedzamy Żółkiew, wracamy. Tym razem po dotarciu z powrotem do Północnego Dworca Autobusowego idziemy na autobus (bo już wiemy że tramwajem nie warto). Na kwaterę docieramy nawet później niż pierwszego dnia (około 18).

Od programu wycieczki była Elka, ale ja wieczorem przeglądając Internet znajduję informacje, że jest tu potencjalnie ciekawy i godny obejrzenia skansen. W środę postanawiamy jechać/iść do skansenu. Janek od razu odmawia, bo się zmęczył -- będzie dalej zapoznawał się z centrum Lwowa.

Plan wprawdzie był żeby jechać do skansenu tramwajem, ale upieram się, że to blisko więc idziemy. Google wytycza dziwną trasę -- po lesie -- długą na 3,1km. Skansen jak najbardziej jest OK i ciekawy, spędzamy tam 1,5h. Wracamy. Tym razem idziemy na trolejbus, tyle że jakoś nie możemy trafić na przystanek. Włączam Xiaomi. Do opery jest 2,1km--eee idziemy. W kwaterze jesteśmy o 14:00. Idziemy z Jankiem na obiad do Premiery Lwowskiej. Podają szybko i sprawnie ale i tak po obiedzie jest już w miarę późno. Jak rano we wtorek łaziłem do mieście, to znalazłem kilka małych muzeów w rynku. Idziemy zobaczyć co tam jest. Pierwsze muzeum jest w budynku palarni kawy. Wchodzimy i z mety chcą nam sprzedawać bilety -- ale za co? Oprócz tabliczki muzeum, i że zbiory etnograficzne, to nic więcej nie wiadomo -- odpuszczamy. Drugie też odpuszczamy. Jakaś wystawa czasowa jest reklamowana, którą uznajemy za nieciekawą i nastawiamy się na zwiedzanie ostatniego -- muzeum poczty -- potencjalnie ciekawe. Podchodzimy do budynku, drzwi otwarte, w środku ewidentnie trwa remont. No to mamy zwiedzone -- idziemy do domu... Elka po drodze jeszcze dostrzega, że Opera jest otwarta i można ją zwiedzać -- to zwiedzamy.

Drohobycz

W czwartek do Drohobycza. Janek znowu zostaje, bo mu się nie chce. Elka za to ustaliła, że można tam pojechać autobusem, który odjeżdża spod dworca kolejowego. Idziemy na dworzec (w miarę blisko, circa 2km). Sugeruję najpierw sprawdzić czy nie da się pociągiem. Są rozkłady, ale dla pewności idziemy do informacji kolejowej, tym chętniej że przed okienkiem nie ma żadnej kolejki. Się okazuje, że nie ma bo płacić trzeba -- 5 hrywien. Najpierw płacisz potem mówią co wiedzą. Nietypowe, ale co kraj to obyczaj. Nawet paragon za te 5 hrywien dali...

Idziemy do kas. Bilet na przejazd kosztuje około 7 PLN. Pomimo tak nędznej ceny mamy rezerwację miejsca, ale -- ciekawostka -- żeby kupić bilet trzeba pokazać paszport. Nasz pociąg jedzie z Diepropietrowska do Truskawca, a nasz wagon to wagon sypialny, tyle że my siedzimy, a nie leżymy. Prycza twarda jak deska, a naprzeciw nas drzemie przykryta kocem dziewczyna. Też jedzie do Drohobycza, co się ujawni po godzinie i 30 minutach (tyle jedzie pociąg ze Lwowa do Drohobycza). Obsługa pociągu przynosi bilet przed stacją, na którą ma się wysiąść (jak w PL w sypialnych); dziewczyna wstaje podnosi pryczę, się okazuje, że tam jest miejsce na bagaże -- wsadza koc i wyciąga swoje walizki. He, być może i my mogliśmy na kocu zamiast na dechach ale to już nieistotne...

W Drohobyczu zbiera się na deszcz. Jedyną taksówkę wynajęli inni Polacy, idziemy na autobus. Trzeba podjechać ponieważ dworzec jest za miastem. Zwiedzanie zaczynamy od cerkwi św. Jura (czyli Jerzego). Za zwiedzanie trzeba zapłacić; w zamian przewodniczka opowiada szczegółowo o historii cerkwi (po ukraińsku, więc osobiście to nie wszystko rozumiem). Wychodzimy z cerkwi--pada deszcz... Elka coś wyczytała o wydobywaniu/kopalni soli w Drohobyczu a pani z cerkwi indagowana w sprawie potwierdza, że faktycznie tuż obok istnieje coś takiego. Idziemy szukać...

Okolica mało malownicza i nie możemy znaleźć. Miejscowy wskazuje konkretne miejsce, wyglądające jak tytułowa Baza z powieści Baza ludzi umarłych Newerlego. Kompleks baraków w stanie daleko posuniętego rozkładu. Przed jednym z baraków wielka kupa kłod drewna i facet z siekierą... Omijamy dziada, pytamy się kobiety, która wylazła z któregoś z baraków. Tak jest fabryka soli, nie ma żadnego muzeum. Generalnie to nie są szczęśliwi, że nas tu widzą, ale pozwalają obejrzeć instalacje. Faktycznie produkują tutaj sól metodą `na króla Ćwieczka': pompują solankę z 50 metrów bodajże, która potem jest odparowywana w dwóch sporych rozmiarów odparnikach a sól ostatecznie `konfekcjonowana' w trzech betoniarkach... Facet rąbiący drewno zapewnia energię potrzebną do odparowania wody. Post factum znalazłem w Internetach coś takiego:

Stara jak Drohobycz `manufaktura', położona między dwiema starymi drewnianymi cerkwiami, do dziś produkuje sławną `Jodowaną Sól Drohobycką' stanowi również `funkcjonujący eksponat' Muzeum Ziemi Drohobyckiej! Za małą opłatą można spokojnie zwiedzić zakład pod nadzorem pracowników, a także zrobić kilka zdjęć na pamiątkę (www.nieznanaukraina.pl/2045/drohobycka-kopalnia-fabryka-soli/).

Dla mnie to był Dickens (Karol) a nie żaden `funkcjonujący eksponat'. Być może dorabiana jest muzealna teoria żeby dziadostwo lepiej wyglądało. W szczególności nigdzie nie widzieliśmy żadnej tablicy informacyjnej iż i jakoby jest to `Muzeum Ziemi Drohobyckiej', które faktycznie istnieje ale w innym miejscu (nie byliśmy)... Nastawienie obsługi też nie było entuzjastyczne do zwiedzania, a zwłaszcza do robienia zdjęć.

Ustalamy, że w zasadzie to wracamy, tyle że po drodze obejrzymy jeszcze miejsca związane z Bruno Szulcem oraz synagogę (udaje się). Ponieważ dworzec kolejowy jest za miastem, a autobusowy bliżej centrum Elka decyduje żeby wracać autobusem. Cena z grubsza ta sama. Atrakcją 20 km jazda po monumentalnych dziurach. Drogę porównywalnej `jakości' widziałem dotąd raz w życiu w Armenii w dolinie Alawerdi.

W piątek odlot o 14:10. Dla pewności ustalamy że na lotnisko pojedziemy o 11:00 więc wizyta w Drohobyczu to był ostatni punkt wycieczki, bo do 11:00 to już nie będziemy niczego zwiedzać (tym bardziej, że większość biznesów zaczyna się tak co najmniej od 9:00). Robimy odprawę przez internet, potem idę na miasto wydrukować karty pokładowe i wydać 200 hrywien co nam zostały. Kupuję ormiański lawasz:-) i ser wędzony. Terminal pustawy, nie to co w GDA. Przed kontrolą bagażu w szczególności nie ma żadnej kolejki... O 14:10 odlot do GDA.

BTW w GDA pan z Wizzair skierował mój plecak do bagażu (nieodpłatnego), bo za duży. Że niby teraz duże bagaże są transportowane w luku mimo, że dalej są `podręczne' (formalnie i zgodnie z nowym regulaminem nie ma gwarancji, że bagaż podręczny poleci z pasażerem). Można oddać od razu lub przy wsiadaniu do samolotu. Wybrałem to drugie, a na płycie lotniska już się nikt nie upominał o mój plecak więc ostatecznie pojechał ze mną a nie w luku bagażowym.

Do pobrania ślady kml ze zdjęciami; zdjęcia; ślady gpx/kml.

poniedziałek, 21 maja 2018

Posokowiec bawarski

UWAGA: Będzie długie i o jeleniu (na zwłoki którego najechałem w sobotę)

Znajomy (korposzczur -- jego własne określenie więc się nie obrazi) się przejął (bardziej niż ja) i mnie mobilizuje do alarmowania świata w temacie: ,,czy etyczne jest, że ktoś dopuścił do tego, że zwłoki jelenia leżą na polu.'' Przypuszczalnie zwierzę zostało postrzelone, uciekło i padło, że tak powiem w pewnym oddaleniu od strzelca. Takie rzeczy się zdarzają oczywiście. Skoro się zdarzają to pewnie są jakoś regulowane choćby zwyczajowo (etycznie/nieetycznie)

No to sru... piszemy w google i mamy (UWAGA: Postrzałek = postrzelone zwierzę; moje komentarze wewnątrz [[ .. ]]):

Rozporządzenie ministra środowiska z dnia 23 marca 2005 r. w sprawie szczegółowych warunków wykonywania polowania i znakowania tusz Dz.U. z dnia 15 kwietnia 2005 r.; Zmieniona wersja (2011-12-14) Dz.U.2011.257.1548. Albo www.lowiecki.pl/gdansk/lowiec/regpol.html Albo Poszukiwanie postrzałka przy użyciu psa.

Art5/8: polowanie na zwierzynę grubą może odbywać się pod warunkiem zapewnienia udziału w poszukiwaniach postrzałka, ułożonego w tym celu psa.

[[Jeżeli nie miał psa to naruszył prawo. To jest zapis chyba obowiązujący od 2010 r.]]

[[To teoria, a teraz praktyka:]]

Udział psa w polowaniu -- czy na co dzień respektujemy przepisy prawa łowieckiego?/Zbigniew Ciemniewski. Ciekawe też tutaj: http://www.bowhunting.pl/pies-dla-mysliwego-z-lukiem/b/34

[[polowanie z łukiem. Ja pierdziu... BTW ale: ]]

Nie każdy myśliwy ma możliwość posiadania własnego psa. Charakter pracy, trudne warunki lokalowe, powodują, że trzymanie psa w domu często staje się niemożliwe. Nie zwalnia to jednak myśliwego z obowiązku szukania postrzałka z pomocą psa. Nie znam koła czy obwodu, w których nie ma przynajmniej jednego psiarza, do którego można zadzwonić po pomoc. Przy niektórych zarządach okręgowych PZŁ istnieją nawet tzw. pogotowia postrzałkowe zrzeszające właścicieli psów ułożonych do poszukiwania postrzałków. Zapisanie numerów telefonów do kolegów posiadających psy i korzystanie z ich pomocy pomoże wypełnić regulaminowy obowiązek każdego myśliwego, który mówi że polowanie na zwierzynę grubą może odbywać się pod warunkiem zapewnienia w poszukiwaniach postrzałka udziału ułożonego w tym celu psa (Art 5. 1. 8 regulaminu polowań).

[[czyli jakaś tam small-afera mogłaby być. Ale niekoniecznie (klubposokowca.org.pl/?page_id=87):]]

Co prawda rozporządzenie ministra środowiska w sprawie szczegółowych warunków wykonywania polowania, zobowiązuje myśliwych do zapewnienia udziału w poszukiwaniach postrzałka ułożonego w tym celu psa, jednak interpretacja pojęcia ,,ułożonego psa'' nie jest podana i w związku z tym jest bardzo dowolna.

[..]

Oczywiście mistrzami w tej dziedzinie pracy myśliwskiej są posokowce.

:-) Oczywiście. Kurde nawet nie wiedziałem że coś takiego istnieje podróże kształcą :-) Do dziś jakby mi ktoś powiedział POSOKOWIEC to bym to z owadem kojarzył prędzej, które to mają bombastic nazwy często.

Więc na koniec: https://www.olx.pl/zwierzeta/psy/q-posokowiec-bawarski/.

A na finalny-koniec: jeżeli ktoś doczytał aż tu i ma wśród znajomych myśliwego, który by się ustosunkował, to będę wdzięczny za komentarz.