wtorek, 21 listopada 2017

Instalowanie Debiana Stretch na SheevaPlug


Stretch zainstalowany

Co to jest SheevaPlug? Przodek rapberryPi. Ciągle używam, bo jest niezawodne, a z rapberryPi jest gorzej -- czasami przestaje działać. Rzadko bo rzadko ale się zdarza.)

Ponieważ SheevaPlug (dalej Szewa) jest taka stara to i Debian na niej do nowych nie należy. Sytuacja dojrzała do wymiany. Mam na szczęście rezerwową/testową Szewę, co ułatwia decyzję, bo w razie problemów z aktualizacją nie zostanę z niczym.

Korzystam z tej samej strony co lata temu kiedy zaczynałem z Szewą, tj. Installing Debian on Plug Computers, która opisuje wszystko detalicznie i zawiera wszystko co potrzeba. Procedura jest prosta:

1. Należy uaktualić firmware zwany U-bootem. W tym celu trzeba się połączyć z Szewą kablem miniUSB-USB i uruchomić na PCcie program cu:

cu -s 115200 -l /dev/ttyUSB0

Teraz trzeba włączyć Szewę, a w terminalu PCta należy szybko nacisnąć dowolny klawisz co przerywa normalną sekwencję startu systemu i U-boot przechodzi do trybu interaktywnego zgłaszając się znakiem zachęty. Polecenie:

Marvell>> version

Pokazuje wersję system. Jeżeli w nazwie jest Marvell albo wersja jest stara (przed 2014/10) to należy dokonać aktualizacji. Przed aktualizację należy koniecznie ustalić MAC adres urządzenia Ja miałem przepisany z dokumentacji na obudowie; jak ktoś nie wie jaki ma adres, to może wydać polecenie:

print ethaddr

Teraz pobieramy stosowny firmware i kopiujemy go na (bootowalny) pendrive. Pendrive wsadzamy do Szewy, po czym wydajemy polecenie:

usb start
fatload usb 0:1 0x0800000 u-boot.kwb

Następnie

nand erase 0x0 0x80000
nand write 0x0800000 0x0 0x80000

Restartujemy szewę

reset

Na koniec przywracamy MAC adres

setenv ethaddr 00:50:43:01:c0:ab
saveenv
reset

Uwaga: przy (re)starcie komputer zawiśnie na etapie ładowania systemu, którego jeszcze nie ma...

2. Poniższy opis zakłada instalowanie systemu z karty SDHC (bo tak jest najprościej, skoro system ma potem być z tejże karty uruchamiany). Zatem należy sformatować kartę SDHC jako ext2 (wyłącznie ext2, nie należy używać innych typu ext4, że niby lepsze). Do tego użyłem gparted.

3. Pobieramy instalator składający się z 2 plików (SheevaPlug without eSATA: uImage and uInitrd). Pobrane plik kopiujemy na sformatowaną kartę. Kartę wsadzamy do Szewy, z którą połączymy się kablem miniUSB/USB i programem cu w sposób identyczny jak w przypadku aktualizacji firmware'a), wydajemy polecenie (jeżeli karta jest sformatowana jako vfat to zamiast ext2load ma być fatload):

ext2load mmc 0:1 0x00800000 /uImage
ext2load mmc 0:1 0x01100000 /uInitrd

Uruchamiamy instalator:

setenv bootargs console=ttyS0,115200n8 base-installer/initramfs-tools/driver-policy=most
bootm 0x00800000 0x01100000

Instalacja trochę trwa, ale jest bezproblemowa. Well, był problem bo zapomniałem wpisać następującej sekwencji (When the installation is done, you have to configure u-boot so it will automatically boot Debian. Interrupt the boot process of u-boot and enter the following commands.):

setenv bootargs_console console=ttyS0,115200
setenv bootcmd_mmc 'ext2load mmc 0:1 0x00800000 /uImage; ext2load mmc 0:1 0x01100000 /uInitrd'
setenv bootcmd 'setenv bootargs ${bootargs_console}; run bootcmd_mmc; bootm 0x00800000 0x01100000'
saveenv

Przyznam się bez bicia, że ponieważ pominąłem ten krok i system zawisł beznadziejnie potrzebna była konsultacja aż samego Marina Michlmayra.

Uwaga: 0:1 to nazwa bootowalnej partycji. Może być inna, można to ustalić wpisując (pierwsza wypisana jest bootowalna):

Marvell>> usb dev
Marvell>> usb part 0

Ostatecznie:

run bootcmd

Znowu dałem D... Nie przywracając MAC-adresu, co objawiło się tym że wprawdzie system się bootował ale instalator nie mógł się połączyć z Internetem. Należy czytać dokumentację uważnie i bez pośpiechu cnd.

Z uwagi na to, że projekt Szewa wydaje sie być dead&burried skopiowałem co trzeba lokalnie tutaj, na wypadek gdyby zniknęło w Internecie.

poniedziałek, 20 listopada 2017

Przeniesienie bloga zarządzanego przez WordPress na inny komputer

Problem jest oto taki, że chcę przenieść kopię bloga (oryginał jest/był na serwerze nazwa.pl) na Sheevaplug (taki rodzaj NAS), która byłaby dostępna przez Internet. Pierwszy krok do likwidacji bloga na nazwa.pl, bo drogo BTW.

Na Sheevaplug jest zainstalowany Debian w wersji Stretch i nie ma WordPressa.

Rozpocząłem od pobrania narzędzia wp-cli ze strony wp-cli.org/. Zainstalowałem toto (prawie) w sposób opisany na ww. stronie, tj.:

https://raw.github.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
php wp-cli.phar --info
chmod +x wp-cli.phar
sudo mv wp-cli.phar ~/bin/wp

Heurystycznie ustaliłem, że treść tego konkretnego klonowanego bloga znajduje się bazie mysql (teksty) oraz w katalogu wp-content, w którym to w szczególności są zdjęcia (wp-content/gallery) oraz filmy i chmara jakiś plików .gif (wp-content/wp-uploads). Oprócz tego są jeszcze katalogi themes, upgrade, plugins, ngg oraz languages. Uprzedzając wydarzenia wszystko kopiuję jak leci ze starej instalacji (w obu jest/będzie ta sama wersja WP). Natomiast teksty z bazy eksportuję (do pliku SQL):

 wp db export

Można też to zrobić logując się do URL-BLOGA/wp-admin. Teraz wszystko ściągam korzystając z rsync (/media/WP-SITE/ oraz /media/WPSQL/ to oczywiście przykłady):

rsync -avzP -e "ssh" USER@BLOG:PATH-TO-WP/wp-content/* /media/WPSITE/
rsync -avzP -e "ssh" USER@BLOG:PATH-TO-WP/_sqldump_/* /media/WPSQL/

Zamiast rsync można użyć ftp albo:

scp -r USER@BLOG:path/to/files/

Teraz pobrałem archiwum WP ze strony wordpress.org/download/ i rozpakowałem je (Uwaga: być może można skopiować po prostu całą starą instalację WP na nowy komputer i będzie działać, ale ja tak nie robiłem.):

wget https://wordpress.org/latest.tar.gz
tar -zxvf latest.tar.gz

Za pomocą klienta mysql stworzyłem użytkownika pn. wordpress, który otrzymał stosowne uprawnienia. Utworzyłem następnie bazę pn. wordpress:

  mysql> CREATE USER 'user'@'localhost' IDENTIFIED BY 'password';
  mysql> CREATE DATABASE wordpress;
  Query OK, 1 row affected (0.00 sec)
 
  mysql> GRANT ALL PRIVILEGES ON wordpress.* TO 'user'@'localhost'
  -> IDENTIFIED BY '*password*';
    Query OK, 0 rows affected (0.00 sec)

Następnie wstawiłem stosowne wpisy do wp-config.php

define('DB_NAME', 'wordpress');
define('DB_USER', '**USER**');
define('DB_PASSWORD', '**PASSWORD**');
define('DB_HOST', 'localhost');
define('DB_CHARSET', 'utf8');

Teraz zaimportowałem treść bloga do bazy:

wp db import kopia-bazy.sql --path='/var/www/html/'

Doczytałem, że trzeba zmienić URLe ze starych na nowe:

wp search-replace 'STARY-URL' 'NOWY-URL' --dry-run

Konkretnie w moim przypadku:

  wp search-replace 'http://nazwabloga.nazwa.pl/' 'http://oberon.pinkaccordions.org/' \
  --path='/var/www/html/' --dry-run
  ## --dry-run nic nie zmienia ale wyświetla raport
  ## jeżeli wszystko jest OK:
    wp search-replace 'http://nazwabloga.nazwa.pl/' 'http://oberon.pinkaccordions.org/' \
     --path='/var/www/html/'

Sprawdzam i nie działa, ale wypisuje, że nie ma jakiegoś theme. No to kopiuję jak leci ze starej instalacji katalogi themes, upgrade, plugins, ngg, languages, o czym już pisałem. Teraz działa.

Jeszcze został problem udostępnienia tego w Interncie poprzez DynDNS. Sprawę komplikuje to, że mam już dwa zarejestrowane serwisy a Tomato wydaje się obsługiwać tylko dwa hosty. Okazuje się wszakże że pole host niekoniecznie musi zawierać pojedynczy wpis, może zawierać listę oddzielonych przecinkami nazw hostów. No to dopisałem następny host z puli, którą mam oraz dopisałem co trzeba w Tomato.

Dodatkowa komplikacja jest taka, że chcę ten sklonowany blog udostępnić na innym komputerze. Konkretnie do tej pory udostępniałem jeden komputer, a teraz będą dwa. Na taką okoliczność oprócz dopisania nazwy hosta do listy trzeba także zmodyfikować wpis w części port forwarding (por. rysunek). Drugi komputer wymaga mianowicie zadeklarowania innego ExPort-u.)

Po tym wszystkim nadal działa:-)

wtorek, 31 października 2017

Geotagowanie zdjęć za pomocą ExifTool

Uwaga: Poniżej zakłada się, że program ExifTool jest używany w środowisku MS Windows.

Pobierz plik ExifTool.exe i umieść go w jakimś katalogu (SomeDir)

Otwórz wiersz polecenia (przejdź do wyszukiwania systemu Windows, wpisz polecenie cmd i otworzy się okno)

W oknie wiersza polecenia zmień katalog na SomeDir.

Geotagowanie zdjęć przy użyciu śladu w formacie GPX

Zdjęcia zrobione z nowoczesnych smartfonów są już geotagowane (jeśli opcja Lokalizacja jest włączona).

Dla aparatów nie wyposażonych w GPS, geotagowanie jest możliwe jeżeli dysponujemy śladem (zarejestrowanym za pomocą zewnętrznego odbiornika GPS.)

Synchronizowanie zdjęć ze śladem GPS

Pobierz plik GPX z odbiornika/rejestratora GPS (dokładna procedura zależy od typu odbiornika GPS) do katalogu SomeDir.

Zrób zdjęcie odbiornika GPS/ekranu lub wyświetlacza, na którym wyświetlany jest zegar z dokładnym czasem (na przykład ekranu komputera/smartfona).

Wpisz w wierszu poleceń:

exiftool -DateTimeOriginal IMG_20171021_113121.jpg 
Date/Time Original : 2017:10:29 11:52:46

Wartość taga DateTimeOriginal określa, że zdjęcie zostało wykonane o 11:52:46. Dokładny czas odczytujemy ze zdjęcia. Załóżmym że czas na zdjęciu wynosi 11:50:19 CET. Zatem DateTimeOriginal jest równe 11:52:46 CET a czas dokładny 11:50:19 CET, stąd różnica 11:32:46 - 11:50:19 = 2min 27s.

Wszystkie odbiorniki GPS wewnętrznie używają/rejestrują wyłącznie używając czasu UTC, nawet jeśli na ekranie pokazywany jest czas lokalny (Por. UTC_offset). Zwykle aparat wewnętrznie korzysta z czasu lokalnego. Jeśli tak jest, należy zadeklarować odpowiednie przesunięcie UTC_offset (w przeciwnym przypadku exiftool używa systemowego przesunięcia czasu względem UTC).

Skopiuj wszystkie zdjęcia do programu SomeDir.

Wpisz w wierszu poleceń:

exiftool -geosync=-02:27 '-geotime<${DateTimeOriginal}+01:00' -geotag my_gps.log SomeDir

Tag Geotime określa punkt w czasie dla którego obliczana jest pozycja GPS. Zapis -geotime<${DateTimeOriginal}+01:00 oznacza, że pozycja jest obliczana według czasu z taga DateTimeOriginal. Zaś dodanie +01:00 ustala CET jako strefę czasową (Przesunięcie +01:00 względem UTC)

Tag Geosync dodaje dodatkowy dryft czasu, jak wyjaśniono powyżej.

Utworzenie pliku KML

Opcja -p służy do generowania plików GPX i/lub KML.

exiftool -fileOrder gpsdatetime -p gpx.fmt SomeDir > SomeTripPhotos.gpx

albo

exiftool -fileOrder gpsdatetime -p kml.fmt SomeDir > SomeTripPhotos.kml

Pliki KML mogą być importowane do Map Google i Google Earth.

Uwaga: jeżeli mapa ma być wyświetlona nie lokalnie, ale na jakimś serwerze WWW (na przykład: http://www.gpsvisualizer.com/), zdjęcia muszą być przesłane na jakiś serwer, a następnie w pliku KML/GPX należy poprawić linki do tychże zdjęć. Dokładna procedura zależy od tego, który serwer jest używany do przechowywania zdjęć.

Przykładowe pliki formatów

gpx.fmt

#[HEAD]<?xml version="1.0" encoding="utf-8"?>
#[HEAD]<gpx version="1.0"
#[HEAD] creator="ExifTool $ExifToolVersion"
#[HEAD] xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
#[HEAD] xmlns="http://www.topografix.com/GPX/1/0"
#[HEAD] xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
#[BODY]<wpt lat="$gpslatitude#" lon="$gpslongitude#">
#[BODY]  <name>$directory/$filename</name>
#[BODY]  <ele>$gpsaltitude#</ele>
#[BODY]  <desc>$directory/$filename</desc>
#[BODY]  <link href="$directory/$filename"><type>large</type></link>
#[BODY]  <link href="$directory/$filename"><type>thumbnail</type></link>
#[BODY]  <time>$gpsdatetime</time>
#[BODY]</wpt>
#[TAIL]</gpx>

kml.fmt

#[HEAD]<?xml version="1.0" encoding="UTF-8"?>
#[HEAD]<kml xmlns="http://earth.google.com/kml/2.0">
#[HEAD]  <Document>
#[HEAD]    <name>My Photos</name>
#[HEAD]    <open>1</open>
#[HEAD]    <Style id="Photo">
#[HEAD]      <IconStyle>
#[HEAD]        <Icon>
#[HEAD]          <href>http://maps.google.com/mapfiles/kml/pal4/icon38.png</href>
#[HEAD]          <scale>1.0</scale>
#[HEAD]        </Icon>
#[HEAD]      </IconStyle>
#[HEAD]    </Style>
#[HEAD]    <Folder>
#[HEAD]      <name>Waypoints</name>
#[HEAD]      <open>0</open>
#[BODY]      <Placemark>
#[BODY]        <description><![CDATA[<br/><table><tr><td>
#[BODY]        <img src='$directory/$filename'
#[BODY]          width='$imagewidth' height='$imageheight'>
#[BODY]        </td></tr></table>]]></description>
#[BODY]        <Snippet/>
#[BODY]        <name>$filename</name>
#[BODY]        <styleUrl>#Photo</styleUrl>
#[BODY]        <Point>
#[BODY]          <altitudeMode>clampedToGround</altitudeMode>
#[BODY]          <coordinates>$gpslongitude#,$gpslatitude#,0</coordinates>
#[BODY]        </Point>
#[BODY]      </Placemark>
#[TAIL]    </Folder>
#[TAIL]  </Document>
#[TAIL]</kml>

Powyższe łącznie z przykładami można pobrać klikając tutaj.

Geotagging images with ExifTool

Note: Below it is assumed that ExifTool is used in MS Windows environment.

Download the ExifTool.exe file and place it in some directory (SomeDir)

Open the Command line (go to windows search, type cmd and the window will open)

In the command line window, change directory to SomeDir.

Geotagging photos using GPX log

Photos taken with modern smartphones are already geotagged (if Location option is On.)

If camera is unable to add geocoordinates geotagging is still possible if GPS log is available (registered with some external GPS receiver/logger).

Synchronize photos with GPS log

Download the GPX file from your GPS receiver/logger (exact procedure depends on the type of GPS receiver) to SomeDir.

Take picture of GPS receiver/or any screen displaying accurate time (PC/Smartphone screen for example).

Type in command line:

exiftool -DateTimeOriginal IMG_20171021_113121.jpg 
Date/Time Original : 2017:10:29 11:52:46

So the file was created at 11:52:46 according to DateTimeOriginal tag. Exact time is depicted. and if for example the time depicted (accurate time) is 11:50:19 CET and DateTimeOriginal is 11:52:46 CET, then the time difference is 11:32:46 - 11:50:19 = 2min 27s, ie. accurate time is obtained by substracting 2min 27s from DateTimeOriginal.

All GPS receivers internally use/record UTC time only, even if they diplay local time (cf UTC_offset). Usually the camera internally uses local time. If it is the case one should declare appropriate UTC_offset (otherwise exiftool uses system offset).

Copy all photos to SomeDir.

Type in command line:

exiftool -geosync=-02:27 '-geotime<${DateTimeOriginal}+01:00' -geotag my_gps.log SomeDir

The Geotime tag specifies the point in time for which the GPS position is calculated. -geotime<${DateTimeOriginal}+01:00 means GPS position is calculated according to DateTimeOriginal and it is CET time (+01:00 offset from UTC)

The Geosync tag specifies extra time drift, as explained above.

Generate KML file

Exiftool -p option have to be used to output files in GPX and/or KML.

exiftool -fileOrder gpsdatetime -p gpx.fmt SomeDir > SomeTripPhotos.gpx

or

exiftool -fileOrder gpsdatetime -p kml.fmt SomeDir > SomeTripPhotos.kml

KML files can be imported to Google maps and or Google earth.

Note: If such a map is not displayed locally but upload to some WWW server (http://www.gpsvisualizer.com/ in the case of GPX file for example), photos have to be uploaded to some server first and then URL to photos fixed. Exact procedure depends on which server is used for storing photos.

Example format files

gpx.fmt

#[HEAD]<?xml version="1.0" encoding="utf-8"?>
#[HEAD]<gpx version="1.0"
#[HEAD] creator="ExifTool $ExifToolVersion"
#[HEAD] xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
#[HEAD] xmlns="http://www.topografix.com/GPX/1/0"
#[HEAD] xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
#[BODY]<wpt lat="$gpslatitude#" lon="$gpslongitude#">
#[BODY]  <name>$directory/$filename</name>
#[BODY]  <ele>$gpsaltitude#</ele>
#[BODY]  <desc>$directory/$filename</desc>
#[BODY]  <link href="$directory/$filename"><type>large</type></link>
#[BODY]  <link href="$directory/$filename"><type>thumbnail</type></link>
#[BODY]  <time>$gpsdatetime</time>
#[BODY]</wpt>
#[TAIL]</gpx>

kml.fmt

#[HEAD]<?xml version="1.0" encoding="UTF-8"?>
#[HEAD]<kml xmlns="http://earth.google.com/kml/2.0">
#[HEAD]  <Document>
#[HEAD]    <name>My Photos</name>
#[HEAD]    <open>1</open>
#[HEAD]    <Style id="Photo">
#[HEAD]      <IconStyle>
#[HEAD]        <Icon>
#[HEAD]          <href>http://maps.google.com/mapfiles/kml/pal4/icon38.png</href>
#[HEAD]          <scale>1.0</scale>
#[HEAD]        </Icon>
#[HEAD]      </IconStyle>
#[HEAD]    </Style>
#[HEAD]    <Folder>
#[HEAD]      <name>Waypoints</name>
#[HEAD]      <open>0</open>
#[BODY]      <Placemark>
#[BODY]        <description><![CDATA[<br/><table><tr><td>
#[BODY]        <img src='$directory/$filename'
#[BODY]          width='$imagewidth' height='$imageheight'>
#[BODY]        </td></tr></table>]]></description>
#[BODY]        <Snippet/>
#[BODY]        <name>$filename</name>
#[BODY]        <styleUrl>#Photo</styleUrl>
#[BODY]        <Point>
#[BODY]          <altitudeMode>clampedToGround</altitudeMode>
#[BODY]          <coordinates>$gpslongitude#,$gpslatitude#,0</coordinates>
#[BODY]        </Point>
#[BODY]      </Placemark>
#[TAIL]    </Folder>
#[TAIL]  </Document>
#[TAIL]</kml>

The above with examples can be download from here

poniedziałek, 16 października 2017

Nigvziani Badrijani czyli gruzińskie roladki z bakłażana


Oryginał z Signagi

W czasie ostatniej wycieczki spróbowaliśmy i bardzo nam smakowały. Takie same lub podobne podano nam podczas wycieczki do Armenii, więc być może to potrawa bardziej kaukaska niż gruzińska.

Generalnie jest to smażony bakłażan z pastą z orzechów włoskich z dodatkiem przypraw. Spróbowałem zrobić wersję opisaną na stronie magicznyskladnik.pl i rezultat jest bardzo dobry. Przepis zaś jest następujący:

Bakłażana kroimy na 3-4 milimetrowe plastry, smarujemy olejem i smażymy do miękkości na patelni grillowej lub zwykłej.

W blenderze miksujemy orzechy włoskie, czosnek, kolendrę, pietruszkę kumin, zmielone ziarna kolendry oraz pieprz (proporce do ustalenia). Autor magicznyskladnik.pl modyfikuje przepis miksując orzechy włoskie i migdały w proporcji 2/1.

Smarujemy bakłażany pastą, zawijamy w rulony lub składamy plastry w pół. W Signagi podawane były na zimno i faktycznie na zimno (z lodówki) jakby lepsze.

Jeszcze każą sypać ziarna granatu na zawinięte/złożone rulony, ale w Signagi każdy rulon miał na wierzchu dokładnie 1 ziarno, więc uważam -- być może niesłusznie -- że ten składnik jest do zaniedbania :-)

Jak się wpisze w google: gruzińskie roladki z bakłażana albo georgian eggplant walnuts albo w oryginale jak ktoś potrafi: ბადრიჯანი ნიგვზით to są setki stron na temat. Jest nawet stosowna strona wiki: Badrijani.

piątek, 13 października 2017

Wycieczka do Gruzji i Armenii


Piekarnia ze słodkimi bułami

Przystanek do Signagi (naprzeciw tej stacji)

Lotem W-wa--Tbilisi start 2.10.2017 22.30 lądowanie 4.00 (różnica czasu) powoduje że leci się niby 5,5 godziny (w rzeczywistości jest to 3,5h) Wsiadamy (Elka i ja) w autobus 37 do miasta i wysiadamy przy stacji metra Samgori skąd mają odjeżdżać marszrutki do Singagi. Jest 6 rano, noc i siąpi deszcz. Nie wiemy dokładnie skąd te marszrutki odjeżdżają. Przystanków marszrutek jest pełno--pytanie z którego jadą tam gdzie chcemy się dostać. Paniki nie ma--wiemy że da się to ustalić, a rozkładem nie ma co się przejmować, bo zawsze coś przyjedzie. Pytanie się wszechobecnych taksówkarzy nie ma sensu -- nic nie powiedzą bo sami będą chcieli zarobić. W tym temacie zresztą nawet nie trzeba się ich pytać -- sami namolnie się oferują: najbardziej konkretny najpierw chce 100 lari (160 PLN), w następnym zdaniu już 70. Jakbyśmy się targowali, to może by i mniej chciał, ale my nie jesteśmy zainteresowani. W końcu ustalamy metodą łażenia tam i z powrotem skąd konkretnie ww. marszrutka odjeżdża. Mówi nam to młody Gruzin -- społeczny kierownk przystanku można powiedzieć, bo łaził po placu wte-i-wewte, informował nas i parę innych zgubionych osób gdzie co jedzie, ale nie wyglądało że sam gdzieś się wybiera i że to jest jego zajęcie za pieniądze.

Czekamy, bo pierwsza marszrutka odjeżdża o 9:00. Czekanie umilamy sobie zwiedzaniem pobliskiego dużego bazaru, który właśnie zaczyna działalność (rano jest). W szczególności nabywamy takie fajne słodkie buły, podobne do chaczapuri, tyle że nadziewane dżemem albo jakąś słodką masą zwierającą orzechy. Taka buła to trylion kalorii ale kurcze smaczna jest, tyle że to chyba nie jest Gruzińskie danie, bo później nigdzie tego nie widzieliśmy. Jakby ktoś był w tych rejonach i chciał spróbować, to sklep z bułami jest pod adresem: 2--3 Mevele St (współrzędne 41.684604/44.854012, obok wejścia na bazar).

Marszrutka do Signagi kosztuje 6 lari (od osoby). Jedzie z nami wycieczka Chińczyków (6 osób) lub osób podobnych do Chińczyków. Nb takich osób w całej Gruzji było dość sporo. Być może było to związane z porą roku, ale mało było Polków, dużo Rosjan no i całkiem sporo turystów pochożych na Kitajców...

Aha, przed wejściem do autobusu kupiliśmy na lotnisku gruzińskie karty SIM za 7 i 5 lari (2Gb/1,5Gb). Jest to super proste--specjalne stoisko było czynne nawet tak wcześnie rano. Trzeba podpisać umowę, ale z pomocą kompetentnego, doskonale mówiącego po angielsku sprzedawcy nie stanowi to problemu. Smarfon się przydał a Internet działa całkiem-całkiem. A jak nie działał, to wspomagałem się OsmAnd -- mapą statyczną czyli zainstalowaną na telefonie...

W Signagi też pada. Idziemy na kwaterę pn Nato & Lado guesthouse, z którą kontaktowaliśmy się przez stronę FB. Mieliśmy jakieś obietnice zwiedzania winnicy/uczestnictwa w zbieraniu winogron, ale ponieważ pada nic z tego. Po południu idziemy do Bodbe obejrzeć klasztor pw. św. Nino. Fajna wycieczka i polecam.

Następnego dnia znowu pada. Decydujemy się na zmianę kwatery na Lagodekhi. Z rana idziemy do muzeum--niewielka instytucja i całe zwiedzanie zajęło nam może godzinę, ale można obejrzeć kilkanaście obrazów Pirosmaniego, więc warto. Wyjaśniło się zresztą iż pomnik na mieście osobnika na ośle to nie jest gruziński hołd dla Sancho Pansy tylko doktor na Ośle --motyw z obrazu Pirosmaniego.

Marszrutką jedziemy do Tsnori, które jest o rzut beretem, potem następną do Lagodekhi. Oczekując na przystanku co chwila jesteśmy nagabywani przez taksówkarzy koniecznie chcących zawieść nas do Lagodekhi za jedyne 20 lari. Próba wytłumaczenia im, że nam się nie spieszy i w związku z tym nie mamy cisku na taksówkę, nie odnosi rezultatu.

W Lagodekhi mamy ambitne plany pokonania wszystkich czterech szlaków opisanych w Internetach, więc nie tracąc czasu idziemy prosto do informacji, która jest kilka kilometrów pod górę. Tam pytamy się o realność naszych planów. (Personel mówi dobrze po angielsku BTW.) Jest kiepsko, pada śnieg (w wysokich górach) więc ten trzydniowy odpada, pada deszcz więc te kilkugodzinne też są wątpliwe, zobaczymy jutro--prognozy są takie że będzie pogoda. Proponują nam kwaterę. No i tu popełniamy błąd...

Reguła Wi-Fi (zwana także warunkiem koniecznym Przechlewskiego)

Otóż wg mnie jak na kwaterze nie ma Wi-Fi to nie ma też wielu innych rzeczy, które my uważamy za minimum a Gruzini niekoniecznie. Ponieważ pan w informacji władał dobrze angielskim zgodziliśmy się na kwaterę bez pytania o detale. Na miejscu okazało się że warunki są fatalne: nie ma Internetu; mieszkanie nieogrzewane a jest dość zimo; w związku z zimnem korzystanie z łazienki a zwłaszcza z wanny jest wybitnie teoretyczne; kuchnia jest, ale wspólna z gospodarzami i o wszystko trzeba prosić, co o tyle jest kłopotliwe że kuchnia wprawdzie jest w domu, ale żeby do niej dość, to trzeba wyjść na zewnątrz, obejść chałupę i wejść z drugiej strony (no czajnik elektryczny w pokoju by rozwiązał sprawę, ale jeszcze na to nie wpadli). Kurcze nawet stół w pokoju nie ma obrusa czy czegoś takiego a do tego w pokoju gdzie mamy spać nie ma światła--jest w pokoju obok, tam gdzie stoi stół, tyle że ten z kolei jest przechodni. Żarówki nie wkręcą, bo po co? Przecież się świeci w tym przechodnim... Rosyjski gospodarzy jest beznadziejny. Nasz niewiele lepszy (jeżeli w ogóle lepszy), ale jak Gruzin mówi dobrze to idzie się dogadać, a jak dwie strony kaleczą, to ustalenie czegokolwiek jest trudne.

Jest już późno (o tej porze roku noc zapada koło 19:00), dziś już niewiele zrobimy. Idziemy do miasta coś kupić do jedzenia i się rozejrzeć. Kupujemy chleb w piekarni--facet pyta czy zawinąć. Da pażausta. Wyciąga gazetę, starannie oddziera pół, i zawija--poczułem się 30 lat młodszy. Śmiejemy się z Elką...

Następnego dnia rano (8:00) idziemy na szlak. Tzn. podwozi nas nasz gospodarz, który ma taksówkę. Pierwsze co to jedzie na stację i za 20 naszych lari kupuje paliwo (za te 20 lari zawiezie nas i przywiezie z powrotem). Ten myk już znamy z poprzednich wojaży i nas wcale nie dziwi czemu nie zatankował przed kursem. Pierwszy szlak (do twierdzy Machi) jest łatwy. Około 13:00 wracamy taksówką (co nas kosztuje ekstra 8 PLN bo musimy dzwonić via Polska--jedyny telefon wykonany w Gruzji). Wychodzi nam, że dziś jeszcze warto zrobić drugi szlak--jak jutro pójdziemy na ten wielodniowy, to już nie zdążymy później. Każemy się wieść do Informacji (stamtąd zaczyna się ten drugi szlak pn Ninoskhevi Waterfall aka Great Waterfall). Ciężko jest wytłumaczyć Gruzinowi, że nie chcemy jeszcze wracać do domu ale udaje się...

Coś trzeba zjeść więc prosimy naszego kierowcę, że my choczom pokupić chaczapuri. To akurat zrozumiał i nas zawiózł do niepozornego lokalu. Wchodzimy nie ma chaczapuri--piecze się i będzie za 10 minut, są jakieś pierogi. No-to-nie, wracamy. Kierowca widząc, że wracamy za szybko pyta się co się stało i sam proponuje że poczeka. No to wracamy z powrotem.

Może te pierogi sobie kupimy co nam proponowali w oczekiwaniu na chaczapuri? Zamawiamy--nie ma. Kurcze dziwne, skończyły się a jakby klientów oprócz nas nie było...


Chaczapuri z Lagodekhi

Chaczapuri za 1,5 lari od sztuki (2,40 PLN) jest super. Na czymś w rodzaju francuskiego ciasta. Bierzemy jeszcze dwa na wynos na kolację. W Gdańsku w piekarni gruzińskiej chaczapuri o jakości take-awaya podgrzewanego na mikrofali z Tbilisi 16 PLN (dla porównania). Taksówkarz pojechał gdzieś i musimy chwilę poczekać (pytał się czy może, nie porzucił nas) -- się okazuje, że złapał kurs, wraca pod chaczapurnię z kobitą z dzieckiem. Po drugiej stronie ulicy jest bank, przywiózł je do banku. No proszę jaki zaradny.

Jedziemy teraz do Informacji pytać się co dalej. Tam już jest inna obsada--bardziej konkretna. Mówią że lepiej nie iść na Black Rock Lake i my też coś czujemy, że to nie byłoby rozsądnie. Trzeba być przygotowanym (buty/śpiwór/aprowizacja) i mieć jakieś tam doświadczenie. To nie dla nas... Pytamy się że może do połowy dość i wrócić -- podobno nie warto. Dwa dni łażenia po lesie a dopiero druga połowa jest super-atrakcyjna widokowo. Ostatni ze szlaków -- Black Grouse Waterfall -- jest zalany wodą i niedostępny No to sprawa jest jasna: dziś jeszcze przejdziemy się do wodospadu a jutro pojedziemy do stolicy.

Drugi szlak jest znacząco trudniejszy i bardziej męczący. Schodzimy ze szlaku praktycznie równo z nadejściem zmierzchu, mając w nogach +20km. W nocy rezerwujemy nocleg w hostelu Envoy, w którym już nocowaliśmy w 2015 roku. Po prostu wysyłam im emaila i po chwili jest potwierdzenie--być może dlatego tak szybko, że już nas znają.

To że tu wszystko na gębę można załatwić w 15 minut i za taką samą cenę jak rezerwowane miesiąc wcześniej, to jasna strona Gruzji:-)

Dwa szlaki zaliczone. Z dwóch co zostały do zaliczenia jeden jest za trudny, a ostatni -- zalany wodą i nie radzą tam chodzić. Rano wiozą nas taksówką (10 lari) na postój marszrutek. Nawiasem mówiąc za pobyt zapłaciliśmy 60 lari a za trzy krótkie kursy taksówką 30 lari. Paradoks. Być może było się targować...

Tbilisi

Marszruta nie staje na Samgori, tylko gdzie indziej. Nie wiemy dokładnie gdzie, ale po chwili widzimy stację metra. Wyciągam smartfona. Przez google maps ustalam, że do Envoya jest 40 minut piechotą, a jak pojedziemy metrem na stację Avlabari, to stamtąd jest 12 minut. Wysiadamy na Avlabari. Eeee, te rejony to my już znamy. Lecimy do Envoya, zostawiamy bagaże i do wieczora chodzimy po mieście.

Ciekawostką są setki kibiców Walii w koszulkach narodowych -- niechybny znak, że dziś wielki mecz w piłkę kopaną. Nawet przez chwilę rozważałem pójście, ale dałem sobie spokój (gdyby grali rugbyści to by nie było dylematu.) Rano pytam się recepcjonistę o wynik--nie wie. You prefer rugby? Yes--nie wiem czy szczerze czy przez grzeczność potwierdził.

Walia wygrywa 1:0.

W sobotę-niedzielę będzie się odbywał festyn pn: Tbilisoba. Więc nasze plany są takie: w Sobotę bierzemy udział w festynie a w niedzielę zapisujemy się na wycieczkę do Armenii. Impreza festynowa okazuje się mało ciekawa: część towarzyska atrakcyjna dla Gruzinów, którzy wszędzie stawiają grille i jedzą te swoje szaszłyki ale to nie dla nas; część artystyczna nieobecna praktycznie, na scenach nic się nie dzieje; cześć handlowe mizerna, kupa ludzi ze wsi sprzedaje to co zwykle. Rozczarowanie i nie polecam.

Normalnie to chodziliśmy na obiad do Machakhela na placu Vakhtang Gorgasali (Nb to chyba sieciówka bo identyko lokal był/jest w Batumi.) ale z uwagi na tłumy szukamy czegoś poza centrum i decydujemy się na Cheburek Cafe, zaraz za łaźniami tureckimi (ulica Ioseb Grishashvili). Chcemy zupę z fasoli, po dwa chinkali i coś warzywnego. Zupy nie ma, chinkali nie ma nawet w menu (to chyba nie jest lokal prowadzony przez Gruzinów). W zamian proponują -- elementary my dear Watson -- czebureki. Niezłe. Pierwszy raz w życiu jadłem, a do czerwca br. to nawet nie wiedziałem co to jest (w czerwcu w Jastrzębiej Górze zobaczyłem toto w budzie fastfudowej).


Tbilisi nocą

W nocy z soboty/niedzielę nie mogę spać, o 4:00 idę zwiedzać Tbilisi/sprawdzić jak wygląda festiwal nocą. Wcale nie wygląda, bo w sumie nic się nie dzieje. Ulice opustoszałe oprócz tych w centrum gdzie są lokale i trochę ludzi się kręci. Tbilisi jest fajnie podświetlona więc wpadam na pomysł pyknięcia paru fotek z wysokości twierdzy Narikala. Idę w górę, nikogo, kompletnie wyludniona okolica. Na górze nawet stragan z całym szajsem pozostawiony bez dozoru... Wracam o 5:30 do Envoya.

Ten nocny wojaż to także empiryczna weryfikacja stanu bezpieczeństwa w Gruzji. Zero strachu wałęsania się po obcym mieście w nocy. Zresztą nie spotkałem tutaj nikogo podobnego do chuligana--chlory są, wiadomo, bo to biedny kraj jest, ale agresywna młodzież--nie widziałem. No i podobno policja jest sprawna/nieprzekupna.

Armenia

Wycieczkę do Armenii wykupiliśmy w hostelu za 135 lari od osoby. W programie wyjazd do trzech klasztorów: Sanahin, Hachpat i Akhtala (w kanionie rzeki Debed), w takiej właśnie kolejności. Wyjeżdżamy o 9.00 około 14:00 mamy obiad przygotowany przez Ormiańską rodzinę we wsi Hachpat. Wracamy około 20:00. Wrażenia mieszane. Pozytywy: widoki, klasztory, obiad (kuchnia Ormiańska IMO jest lepsza od gruzińskiej, która jak dla mnie jest zbyt kaloryczna w części jarskiej, że tak powiem oraz obok moich upodobań z tymi swoimi szaszłykami i innym czerwonym mięsem), fajne towarzystwo z całego świata (USA, Nowa Zelandia, Australia, Niemcy no i my). Negatywy: straszna bieda i zdegradowana do niepojętych granic infrastruktura/domy, które trzeba oglądać...

Odmeldowujemy się z Envoya. Kupuję na mieście chaczapuri w wersji take-away i jemy je na trawniku obserwując dogorywającą imprezę pn. Tbilisoba. Stoiska już w większości są zamknięte, ludzie z prowincji zwijają biznesy. W hostelu twierdzili, że na scenie w pobliżu łaźni będzie gala koncert, ale słusznie stwierdziliśmy że to false-alarm jest i nie poszliśmy tam (podejrzane wydało się miejsce dla tego koncertu--toż tam w ogóle nie ma przestrzeni dla widzów). Że było to słuszne posunięcie potwierdza kompletna cisza -- gdyby grali/śpiewali byłoby coś słychać--nasz trawnik jest niedaleko.

Nota Bene Elka-optymistka sugeruje jechać na lotnisko i tam coś zjeść (don't do that--ceny z księżyca), na szczęście jej nie słucham. Około 22:00 jedziemy na lotnisko autobusem linii 37. Do odlotu zostało nam 7 godzin, ale w sumie nie ma nic do roboty. Od Envoya do najbliższego przystanku 37 jest blisko, należy tylko przejść przez most, a następnie kierując się na stację metra, minąć ją i szukać pierwszego przystanku autobusowego po prawej stronie. Przejazd jak zwykle, tj. pół lari czyli około 80 groszy.


Sklep przy lotnisku

Na lotnisku nie ma co robić, zabijając czas można by coś kupić i zjeść--ceny wszakże zniechęcają. Moja ulubiona, bo duża, kawa Americano za 14 PLN, i jest tego może 100ml (jak to jest Americano to jak wygląda Espresso:-?). W Wa-wie to się w Costa dostaje za podobną cenę pół litra.

Nie kupuję, idą sobie sprawdzić przed lotniskiem. I jest sukces. Obok efektownego posterunku policji (Isani Samgori PoliceStation #6 na google maps) jest mały sklepik, a w nim normalne ceny. He, he... ostatnia sprawiedliwa na wschód od Tbilisi (sprzedawczyni zwana w PRL sklepową) śpi, stukam w szybę: Kofi u was jest. -- Jest... Jest też lodówka z lodami: katoryje morożenoje charosze? -- Wsie charosze... No i faktycznie dobre były.

Tbilisi-Wwa start 9.10.2017 05.05 rano.

Przydatnie informacje

Wycieczka wyszła nam 1500PLN/łep z czego połowa to cena biletów lotniczych. Specjalnie się nie ściskaliśmy z kasą wię pewnie dałoby radę i taniej, ale po co?

Miejsce odjazdu marszrutek spod Samgori do Singagi: 2 Ketevan Dedofali Ave (wsp. geograficzne: 41.686001/44.852066)

Chaczapurnia w Lagodekhi: 23 Qiziki St., naprzeciw oddziału Libery Bank (jeżeli czegoś nie pokręciłem)

Ślad ze zdjęciami do twierdzy Machi oraz wodospadu Ninoskhevi

Tani sklepik pod lotniskiem: po lewej patrząc od terminala w stronę miasta, tj. przed posterunkiem policji (wsp. geograficzne 41.673424/44.961378)

Ślady naszych wycieczek 2014/2015/2017 (czerwony -- 2014, niebieski -- 2015)

Zdjęcia z wycieczki z 2017

Dane w formacie GPX/KML do pobrania tutaj

wtorek, 10 października 2017

Trzecia podróż na Kaukaz

Właśnie wróciliśmy z Elką z Gruzji i Armenii, która to wycieczka była naszą trzecią w tamte rejony. Zanim więcej na temat, na razie podsumowanie naszych wyczynów w postaci pliku GPX (na pierwszej mapie czerwona kreska oznacza rok 2014, niebieska -- 2015, ciemno-zielona -- 2017): 2014-17201420152017

Ponieważ powyższe linki prowadzą do dość rachitycznego serwerka, to na wypadek gdyby ów zniknął albo przestał działać kopie plików GPX są w repozytorium na githubie tutaj

środa, 27 września 2017

Żuławy wKoło 2017 -- podsumowanie

Podsumowanie wyników dla lat 2015--2017

z16 <- read.csv("wyniki_zulawy_2016_D.csv", sep = ';',  header=T, na.string="NA", dec=",");
aggregate (z16$time, list(Numer = z16$dist), summary)
z16$year <- 2016;

z15 <- read.csv("wyniki_zulawy_2015_D.csv", sep = ';',  header=T, na.string="NA", dec=",");
aggregate (z15$time, list(Numer = z15$dist), summary)
z15$year <- 2015;

z17 <- read.csv("wyniki_zulawy_2017_D.csv", sep = ';',  header=T, na.string="NA", dec=".");
aggregate (z17$time, list(Numer = z17$dist), summary)
z17$year <- 2017;

zz15 <- z15[, c("dist", "kmH", "time", "year")];
zz16 <- z16[, c("dist", "kmH", "time", "year")];
zz17  <- z17[, c("dist", "kmH", "time", "year")];

zz <- rbind (zz15, zz16, zz17);

## tylko dystans 140
zz140 <- subset (zz, ( dist == 140 ));
sum140 <- aggregate (zz140$kmH, list(Numer = zz140$year), summary)

boxplot (kmH ~ year, zz140, ylab = "Śr.prędkość [kmh]", col = "yellow", main="140km" )

## tylko dystans 55
zz75 <- subset (zz, ( dist > 60 & dist < 90 ));
sum75 <- aggregate (zz75$kmH, list(Numer = zz75$year), summary)
sum75
boxplot (kmH ~ year, zz75, ylab = "Śr.prędkość [kmh]", col = "yellow", main="80/75km" )

## tylko dystans 55
zz55 <- subset (zz, ( dist < 60 ));
sum55 <- aggregate (zz55$kmH, list(Numer = zz55$year), summary)
sum55
xl <- paste ("średnie 2015=", sum55$x[1,4], "kmh   2016=",
  sum55$x[2,4], "kmh   2017=", sum55$x[3,4], " kmh")

  boxplot (kmH ~ year, zz55, xlab = xl,
  ylab = "Śr.prędkość [kmh]", col = "yellow", main="55km" )

A ja (numer 418) byłem 70 w kategorii 140 km, z czasem 5:42:03 co dało 24,56 kmh przeciętną. Do pierwszego bufetu się spinałem, potem już nie...

wtorek, 26 września 2017

Obracanie wideo za pomocą ffmpeg

Raz na jakiś czas mi się zdarza źle założyć kamerę i obraz jest odwrócony do góry nogami (albo przekręcony o 90 stopni). Film z Żuławy wKoło jest do-góry-nogami. Próbuję postawić go na nogi rozpoczynając od mencodera:

time mencoder -vf flip -o plik.avi -oac copy -ovc lavc plik2.avi
## 26min ale słaba jakość

Słaba jakość. Pewnie można poprawić ale nie wiem jak i nie chce mi się zgłębiać dokumentacji. Zamiast tego zmieniam konwerter na ffmpeg

time ffmpeg -i plik.we -vf vflip -c:a copy plik.wy
## 75 minut (jedziemy lewa strona)

Prawie dobrze, tj. głowa jest na górze a nogi na dole, ale obraz jest w lustrze (jedziemy lewą stroną ulicy, napisy są w lustrzanym odbiciu itp...). W google można znaleść taki przepis:

time ffmpeg -i plik.we -vf "transpose=0" -c:a copy plik.wy

Jak poprzednio tylko przekręca lustro w pionie bez sensu. Działa (prawie) prawidłowo następujące wywołanie:

time ffmpeg -i plik.we -vf "transpose=2,transpose=2" -c:a copy plik.wy

Prawie, ponieważ:

ffmpeg -i plik.wy

Zgubiły się napisy zawierające współrzędne geograficzne, ale to też da się naprawić:

time ffmpeg -i plik.we -vf "transpose=2,transpose=2" -c:a copy -c:s copy plik.wy

poniedziałek, 25 września 2017

Chancellor Merkel victory for a visual person

Change in number of seats won by party (AfD is brown of course regardless official party colors :-):-)

library(ggplot2)

df <- read.csv("de.csv", sep = ';', header=T, na.string="NA");

ggplot(df, aes(x=party, y=diff, fill=party )) +
geom_bar(stat="identity") +
geom_text(aes(label=diff), vjust=-0.5) +
labs(x = "", y="change") +

ggtitle("German elections results (#MP change)") +

## AfD is brown regardless official party colors :-)
scale_fill_manual(values=c("#8B4513", "#56B4E9",
"yellow", "green", "red", "#ff6666") )

Współrzędne geograficzne zarejestrowane kamerą Contour+

Contour+ ma GPSa i rejestruje współrzędne geograficzne, tyle że do niedawna nie bardzo wiedziałem jak (słusznie podejrzewałem że w postaci napisów aka subtitles). Wreszcie rozkminiłem jak to działa, a zmobilizowały mnie filmy zarejestrowane podczas imprezy Żuławy wKoło 2017.

Najpierw trzeba ustalić co jest w środku pliku .mov:

ffmpeg -i FILE0037.MOV
## ## ##  
Stream #0:2(eng): Subtitle: mov_text (text / 0x74786574), 1 kb/s (default)

Teraz można wyciągnąć napis znajdujący się w strumieniu (stream) 2:

ffmpeg -i FILE0037.MOV -vn -an -codec:s:0.2 srt file0037_2.srt

W pliku file0037_2.srt jest coś takiego:

692
00:11:31,000 --> 00:11:32,000
$GPRMC,061159.00,V,,,,,,,240917,,,N*7E
$GPGGA,061159.00,,,,,0,04,2.18,,,,,,*53

693
00:11:32,000 --> 00:11:33,000
$GPRMC,061200.00,A,5412.74161,N,01906.66188,E,18.465,202.51,240917,,,A*50
$GPGGA,061200.00,5412.74161,N,01906.66188,E,1,04,2.18,6.5,M,32.4,M,,*58

Czyli jest to zwykły plik napisów w formacie SRT, tj. sekwencja rekordów składających się z wierszy tekstu. Pierwszy wiersz zawiera numeru napisu (692 na przykład). Drugi wiersz określa czas wyświetlania napisu (początek --> koniec). Kolejne wiersze to tekst napisu. W przykładzie powyżej napis 692 jeszcze nie złapał fiksa, a napis 693 już tak. Współrzędne są zarejestrowane w postaci par zdań (sentences) GPRMC/GPGGA w standardzie NMEA. Do konwersji czegoś takiego na format GPX na przykład można zastosować gpsbabela

gpsbabel -i nmea -f file.srt -o GPX -F file.gpx

Ale wtedy gubi się informację z pierwszych dwóch wierszy rekordu, a jest ona niezbędna do synchronizacji obrazu ze współrzędnymi w programach nie potrafiących wykorzystać napisów wbudowanych. Chciał-nie-chciał musiałem rozpoznać NMEA i dokonać konwersji po swojemu:

$GPRMC,time,###,dd.mm,N/S,dd.mm,E/W,speed,###,date,###,###,###
$GPGGA,time,dd.mm,N/S,dd.mm,E/W,q,s,###,ele,M,###,M,###,### 

Gdzie: speed -- prędkość w węzłach czyli milach/godzinę; date -- data w formacie ddmmyy; time -- czas w formacie hhmmss.ss; dd.mm -- współrzędne geograficzne w formacie stopnieminuty.minuty tj 5412.74161 oznacza 54 stopnie 12.74161 minut a 01906.66188 oznacza 19 stopni 6.66188 minut (uwaga: szerokość/długość ma różną liczbę cyfr przed kropką dziesiętną); N/S/E/W -- kierunki geograficzne (north, south itp); q -- jakość sygnału (niezerowa wartość jest OK); s -- liczba satelitów; ele -- wysokość npm. (w metrach na szczęście w przypadku Contoura+). Zawartość pól oznaczona jako ### nas nie interesuje. Symbol M oznacza jednostkę miary (metry), z czego by wynikało, że różne odbiorniki GPS mogą zapisywać informacje o wysokości z wykorzystaniem innych jednostek miary.

Teraz banalny skrypt Perlowy zamienia SRT na format GPX dodając informacje o numerze napisu i czasie wyświetlania w postaci stosownego elementu cmt

  <trkpt lat="54.212360" lon="19.111031">
    <ele>6.500000</ele>
    <time>2017-09-24T06:12:00Z</time>
    <speed>9.499208</speed>
    <cmt>693 00:11:32,000 --> 00:11:33,000</cmt>
  </trkpt>

BTW nie ma elementu speed w specyfikacji schematu GPX, ale na przykład gpsbabel taki element wstawia i jakoś to działa. Sprawa wymaga zbadania.

Uwaga: Garmin Virb Edit nie czyta dokumentów GPX w wersji 1.0 -- musi być wersja 1.1. W praktyce oznacza to, że element gpx powinien posiadać atrybuty version oraz xmlns o następujących wartościach

<gpx version="1.1" xmlns="http://www.topografix.com/GPX/1/1">
 

Skrypt pn. cc2gpx.pl do konwersji SRT→GPX jest tutaj.

sobota, 23 września 2017

Przed Żuławy w Koło 2017

Jutro planuję przejechać 140km biorąc udział w imprezie pn. Żuławy wKoło 2017. Niby Żuławy a profil trasy sugeruje jakieś istotne wzniesienie w okolicach 25--40km:

Uważnie przyjrzenie się liczbom (zwłaszcza na osi OY) pozwala stwierdzić, że jest to złudzenie, wynikające z różnicy w jednostkach miary obu osi (kilometry vs metry). W rzeczywistości góra tam jest symboliczna o czym można się przekonać robiąc wykres nachyleń. Żeby pozbyć się przypadkowych błędów związanych z niedokładnością pomiaru oryginalne 673 punktowe dane zostały zmienione na 111 punktowe (uśrednienie minimum 1 km) lub 62 punktowe (uśrednienie minimum 2 km).

Przy czym uśrednienie minimum $x$ oznacza obliczenie nachylenia dla najkrótszego odcinka kolejnych $n$ punktów z oryginalnego śladu GPX, który będzie dłuższy niż $x$.

Skrypty R/dane są tutaj. Oryginale ślady GPX/TCX skopiowane ze strony ŻwK są tutaj.

poniedziałek, 18 września 2017

Duńskie crime story z równością płci w tle

W Danii doszło do morderstwa. Ponieważ ofiarą jest kobieta i dziennikarka, do tego znana w pewnych kręgach sprawa jest komentowana (w tychże kręgach). Niejaka i bliżej mi nieznana pani Sruthi Gottipati z Guardiana w rubryce Gender zresztą czyli bynajmniej nie kryminalnej stwierdza: After traveling and reporting in Africa, Asia and the Caribbean, it was in her native Scandinavia, a supposed bastion of gender parity, in which Kim has disappeared. Zatem wg. pani Gottipati nastąpił paradoks: zamordowana uszła z życiem w krajach znanych z męskiej opresji wzg. kobiet, a nie dała rady w państwie, który jest bastionem równości płci.

Po pierwsze w swoim ptasim móżdżku pani Gottipati nie potrafi zauważyć, że jak równość to równość. Co to za równość jak ofiarą morderstwa może paść wyłącznie facet, a jak kobieta to paradoks i skandal. W bastionie równości rozkład ofiar (i sprawców) powinien być fifty-fifty, a jest zaledwie 30--70 (na niekorzyść kobiet, w sensie że tylko 30% ofiar to kobiety). Dania ma tutaj jeszcze sporo do nadrobienia zanim będzie można ją nazwać bastionem równości.

Po drugie i to mnie zastanawia: pani Gottipati używa terminu gender parity, który jest dużo mniej popularny niż gender equality. Wg eige.europa.eu/ Gender parity is a numerical concept related to gender equality, czyli jest to miara równości płci. Zatem Dania jest bastionem pod względem poprawności wskaźników mierzących równość płci. Nie wiem czy pani Gottipati chciała to faktycznie powiedzieć (być może nie rozróżnia po prostu obu pojęć), ale wygląda że coś takiego chlapnęła--idiotyzm do kwadatu.

No i po trzecie paradoks Gottipati ma się jak pięść do nosa w konfrontacji nie tylko z zwykłą logiką ale z danymi. Bo jeżeli jednak przyjmiemy za pozytywną sytuację, w której współczynnik zabójstw nie jest jednakowy wg. płci, tylko dla kobiet jest mniejszy, to w wybranych krajach kształtuje się on (ten współczynnik) następująco:

https://en.wikipedia.org/wiki/Homicide_statistics_by_gender
Kraj   Liczba zabójstw  WspZ       %M      %K    Rok
Czech Republic	   105	 1.0	54.3%	45.7%	2011
Denmark	            47	 0.8	66.0%	34.0%	2010
Finland	            89	 1.6	53.9%	46.1%   2010
Norway	           111	 2.2	53.2%	46.8%   2010
Poland	           449	 1.2	73.2%	26.8%	2010
Colombia	14,670	30.8	91.6%	 8.4%   2012
Brazil	        50,108	25.2	89.8%	10.2%	2010
Argentina	 2,237	 5.5	83.6%	16.4%   2011
Pakistan	13,846	 7.7	76.7%	23.3%   2010
Indonesia	 1,456	 0.6	80.3%	19.7%   2010
Dominican Rep.   2,268	22.1	91.1%	 8.9%	2010
Honduras	 7,172	90.4	93.2%	 6.8%	2010
gdzie: %M/%K -- odsetek ofiar mężczyźni/kobiety;
WspZ -- współczynnik zabójstw
czyli liczba zabójstw / 100 tys mieszkańców

Kilka interesujących stron przy okazji United Nations Office on Drugs and Crime oraz ourworldindata.org

PS: lokalna tuba lewactwa na PL czyli politruka.pl in-extenso relacjonowała całą ,,aferę'' łącznie ze bezrefleksyjnym skopiowaniem stosownego fragmentu z Guardiana (dowód w załączeniu)

poniedziałek, 11 września 2017

Czytelnictwo prasy

Punktem wyjścia są dane ze strony ZKDP (w formacie Excel.) Ponieważ pobieram je od pewnego czasu mam tego więcej niż jest na ww. stronie bo od stycznia 2015 do lipca 2017, czyli 31 plików. Ręczna konwersja byłaby zatem ciut za bardzo czasochłonna.

  for i in *.xls do
    oocalc --headless --convert-to csv $i ;
    # albo ssconvert -v $i `basename $i .xls`.csv ;
    done
  # Wyciągam dane dotyczące sprzedaży ogółem dla SE
  grep 'Super Ex' *.csv | awk -F ',' '{print $7} ' > se_sales.csv
  # Analogicznie dla innych tytułów

Uwaga: program ssconvert znajduje się w pakiecie gnumeric, oocalc to oczywiście składni Libre/OpenOffice.

Wielkości sprzedaży dla trzech najpoczytniejszych tytułów pokazują wykresy liniowe (pierwszy w tys egz. a drugi w procentach nakładu ze stycznia 2015 r.)


Sprzedaż w tys egz.

Sprzedaż w % poziomu ze stycznia 2015
library(ggplot2)
library(reshape2)

df <- read.csv("newspaper_sales_2015-17.csv", sep = ';',
               header=T, na.string="NA");

meltdf <- melt(df,id="month")

ggplot(meltdf,aes(x=month, y=value, colour=variable, group=variable)) +
  geom_line() +
  ylab(label="sales [ths]") +
  theme(legend.title=element_blank()) +
  scale_x_discrete (breaks=c("2015-01-01", "2015-06-01",
     "2016-01-01", "2016-06-01", "2017-01-01",  "2017-06-01"),
  labels=c("2015-01", "2015-06", "2016-01", "2016-06",
     "2017-01", "2017-06")  )

# https://stackoverflow.com/questions/10085806/extracting-specific-columns-from-a-data-frame
obs <- df[,c("month")]

normalize <- function(x) { return (x /x[1] * 100 )  }
dfN <- as.data.frame(lapply(df[-1], normalize))

# https://stackoverflow.com/questions/10150579/adding-a-column-to-a-data-frame
dfN["month"] <- obs

str(dfN)

meltdf <- melt(dfN,id="month")

# https://www.r-bloggers.com/what-is-a-linear-trend-by-the-way/
pN <- ggplot(meltdf,
 aes(x=month, y=value, colour=variable, group=variable)) + geom_line() +
 ylab(label="sales [ths]") +
 theme(legend.title=element_blank()) +
 stat_smooth(method = "lm", se=F) +
  scale_x_discrete (breaks=c("2015-01-01", "2015-06-01",
     "2016-01-01", "2016-06-01", "2017-01-01",  "2017-06-01"),
  labels=c("2015-01", "2015-06", "2016-01",
  "2016-06", "2017-01", "2017-06")  )

  pN

Spadek widoczny na wykresach można określić liczbowo na przykład szacując linię trendu:

# Trend liniowy
# http://t-redactyl.io/blog/2016/05/creating-plots-in-r-using-ggplot2-part-11-linear-regression-plots.html

# http://r-statistics.co/Time-Series-Analysis-With-R.html
seq = c (1:nrow(dfN))
dfN["trend"] <- seq

trendL.gw <- lm(data=dfN, gw ~ trend )
trendL.fakt <- lm(data=dfN, fakt ~ trend )
trendL.se <- lm(data=dfN, se ~ trend )

trendL.gw
trendL.fakt
trendL.se

Współczynniki trendu dla GW, Faktu i SE są odpowiednio równe -1.114 -0.6415 -0.4301, co należy interpretować następująco: przeciętnie z miesiąca na miesiąc nakład spada o 1,11%, 0,64% oraz 0,43% nakładu ze stycznia 2015 r., odpowiednio dla GW, Faktu i SuperExpresu.

Dane i wyniki są tutaj

niedziela, 10 września 2017

Żuławy w koło 2016

Żuławy w koło to maraton rowerowy (czyli przejazd rowerem na dłuższym dystansie -- nie mylić z wyścigiem) organizowany od paru lat na Żuławach jak nazwa wskazuje. Sprawdziłem jak ta impreza wyglądała pod kątem prędkości w roku 2016. W tym celu ze strony Wyniki żUŁAWY wKOŁO 2016 ściągnąłem stosowny plik PDF z danymi, który następnie skonwertowałem do pliku w formacie XLS (Excel) wykorzystując konwerter on-line tajemniczej firmy convertio.pl. Tajemniczej w tym sensie, że nie znalazłem informacji kto i po co tą usługę świadczy.

Konwersja (do formatu CSV) -- jak to zwykle konwersja -- nie poszła na 100% poprawnie i wymagała jeszcze circa 30 minutowej ręcznej obróbki. Być może zresztą są lepsze konwertery, ale problem był z gatunku banalnych i wolałem stracić 30 minut na poprawianiu wyników konwersji niż 2 godziny na ustalaniu, który z konwerterów on-line konwertuje ten konkretny plik PDF (w miarę) bezbłędnie.

Po konwersji wypadało by sprawdzić (chociaż zgrubnie) czy wszystko jest OK.

## Czy każdy wiersz zawieraja 9 pól (powinien)
$ awk -F ';' 'NF != 9 {print NR, NF}' wyniki_zulawy_2016S.csv

## Ilu było uczestników na dystansie 140km?
$ awk -F ';' '$7 ==140 {print $0}' wyniki_zulawy_2016S.csv | wc -l
133

## Ilu było wszystkich (winno być 567 + 1 nagłówek)
$ cat wyniki_zulawy_2016S.csv | wc -l
568 # ok!

Przykładowy wykres pudełkowy

Do analizy statystycznej wykorzystano wykres pudełkowy (porównanie wyników na różnych dystansach) oraz histogram (rozkład średnich prędkości na dystansie 140km). BTW gdyby ktoś nie wiedział co to jest wykres pudełkowy to wyjaśnienie jest na rysunku obok. Objaśnienie: Me, $Q_1$, $Q_3$ to odpowiednio mediana i kwartyle. Dolna/górna krawędź prostokąta wyznacza zatem rozstęp kwartylny (IQR). Wąsy ($W_L$/$W_U$)są wyznaczane jako 150% wartości rozstępu kwartylnego. Wartości leżące poza ,,wąsami'' (nietypowe) są oznaczane kółkami.

Ww. wykresy wygenerowano następującym skryptem:

#
co <- "Żuławy wKoło 2016"
#
z <- read.csv("wyniki_zulawy_2016_C.csv", sep = ';',
  header=T, na.string="NA", dec=",");

aggregate (z$meanv, list(Numer = z$dist), fivenum)

boxplot (meanv ~ dist, z, xlab = "Dystans [km]",
    ylab = "Śr.prędkość [kmh]", col = "yellow", main=co )

## tylko dystans 140
z140 <- subset (z, ( dist == 140 ));

## statystyki zbiorcze
s140 <- summary(z140$meanv)
names(s140)

summary_label <- paste (sep='', "Średnia = ", s140[["Mean"]], 
  "\nMediana = ", s140[["Median"]],
  "\nQ1 = ", s140[["1st Qu."]],  "\nQ3 = ", s140[["3rd Qu."]],
  "\n\nMax = ", s140[["Max."]] )
# drukuje wartości kolumny meanv
# z140$meanv
# drukuje wartości statystyk zbiorczych
s140

# wykres słupkowy
h <- hist(z140$meanv, breaks=c(14,18,22,26,30,34,38), freq=TRUE, 
   col="orange", 
   main=paste (co, "[140km]"), # tytuł
   xlab="Prędkość [kmh]",ylab="L.kolarzy", labels=T, xaxt='n' )
# xaxt usuwa domyślną oś 
# axis definiuje lepiej oś OX
axis(side=1, at=c(14,18,22,26,30,34,38))
text(38, 37, summary_label, cex = .8, adj=c(1,1) )

Dane i wyniki są tutaj

środa, 6 września 2017

O lepsze liczenie kadencji

Informacja o kadencji jest w pliku .tcx rejestrowana (przez GarminaEdge 500) w następujący sposób:

  <Activities>
    <Activity Sport="Biking">
      <Lap StartTime="2017-08-31T14:51:16Z">
 <Cadence>77</Cadence>
 ...
 <Track>
     <Trackpoint>
             <Time>2017-08-31T14:52:02Z</Time>
             <Cadence>0</Cadence>
          </Trackpoint>
   <Trackpoint>
      <Time>2017-08-31T14:52:06Z</Time>
      <Cadence>46</Cadence>
   </Trackpoint>
   <Trackpoint>
            <Time>2017-08-31T14:52:07Z</Time>
     <Cadence>53</Cadence>
   </Trackpoint>

Lap-ów może być wiele. Każdy zawiera element Track, w którym zapisana jest informacja o fragmencie trasy. Pomiędzy LapTrack znajduje się nagłówek zawierający różne obliczone/zbiorcze informacje, m.in. średnią kadencję. Co by oznaczało, że w powyższym przykładzie średnia kadencja wynosiła 77 obrotów/min. Na odcinku od 14:52:02Z do 14:52:06Z (4 sekundy) średnia kadencja wyniosła 46 o/min, zaś na odcinku 14:52:06Z--07Z (1s) 53 o/min.

Można też policzyć kadencję samodzielnie, co pozwoli na uzyskanie dodatkowej informacji. Liczenie kadencji jest proste. Mnożąc średnią kadencję odcinka razy czas w sekundach otrzymamy liczbę obrotów korby na tym odcinku (kadencję należy podzielić przez 60 bo jest podana w minutach). Odcinki o zerowej kadencji pomija się (Garmin też tak oblicza BTW). Dzieląc łączną liczbę obrotów przez czas otrzymamy średnią kadencję. Ja dodałem opcję pomijania odcinków o pewnej minimalnej prędkości (np. 8 kmh) -- takie odcinki to zwykle jakieś nietypowe fragmenty, zaniżające tylko średnią.

#!/usr/bin/perl
# Cadence calculator for GarminEdge tcx files (or converted fits)
# tprzechlewski@gmail.com
use Getopt::Long;

my $prev_Time = -1;
my $parsingTrack ='N';
my $regCadence = 'N';
my $min_speed = -1; # minimum speed
my $trackNo=1;

GetOptions( "s=f"  => \$min_speed, );
$min_speedMS = ($min_speed *1000)/3600.0;

if ($min_speed > 0) {
  print "*** Segments with speed below $min_speed kmh skipped ***\n";
}

while (<>) {
  chomp();

  # Order is importany (first check for <Track>:
  if ( /<Track>/ ) {
    if ( $regCadence eq 'N' ) {
      ## Check if Cadence is registered
      print STDERR "*** No cadence registered! ***\n";
      exit 1;
    } else {
      $parsingTrack = 'Y' ; print STDERR "### Parsing track #$trackNo...\n";
      $trackNo++;
    }
  }

  # Parsing header:
  if ($parsingTrack eq 'N' ) {
    if ( /<TotalTimeSeconds>/) {
      $edge_LapTime = xmlEleValue('TotalTimeSeconds', $_) ; }
    elsif (/<Cadence>/) {
      $edge_LapCadence = xmlEleValue('Cadence', $_) ; $regCadence = 'Y' }
    elsif (/<DistanceMeters>/) {
      $edge_LapDist = xmlEleValue('DistanceMeters', $_) ;  }
    ##print STDERR "## Parsing track info: $_\n";
    next;
  }


  ## start parsing Track now:
  if (/Speed>/)  { $speed = xmlEleValue ('Speed', $_);
  } elsif ($_ =~ /<Time>(.*)T(.*)Z<\/Time>/ ) {
    $time = $2;
    ($h, $m, $s )  = split /:/, $time;
    $current_time = $h * 60 * 60  + $m * 60 + $s ;
    ##print STDERR "$current_time\n";
  } elsif (/<Cadence>/ ) {
    $cadence = xmlEleValue ('Cadence', $_);
  } elsif (/<DistanceMeters>/ ) { 
    $distance = xmlEleValue ('DistanceMeters', $_);
  } elsif ($_ =~ /<\/Trackpoint>/ ) {

    if ( $prevTime > 0 ) {## pomija pierwsze
      $lastTime = $current_time ;
      if ($cadence > 0 && $speed > $min_speedMS ) {
 $timeDiff = $current_time - $prevTime; 

 $total_time_cycled += $timeDiff ;
 $total_cycles += $cadence * $timeDiff / 60;

 $prevTime = $current_time ;
      }
      else {
 $timeDiff = $current_time - $prevTime; 

 $total_time_idle += $timeDiff ;

 $prevTime = $current_time ;
      }

    } else {
     $prevTime = $current_time ;
     $firstTime = $current_time ;
  }

 }

if ( /<\/Track>/ ) {
   $total_Time = $total_time_idle + $total_time_cycled;

   printf "Time = Idle: %d s Spinning: %d s Total: %d s\n", $total_time_idle,
      $total_time_cycled, $total_Time;
   printf "Time = Idle: %.2f%% Spinning: %.2f%% Total: %.2f%%\n",
      $total_time_idle/$total_Time *100,
      $total_time_cycled/$total_Time * 100, $total_Time/$total_Time *100;

   print "Rotations (total) = $total_cycles\n";
   print "Mean cadence (computed) = " . $total_cycles/$total_time_cycled * 60 . "\n";

   $totalTimeTime = $lastTime - $firstTime;

   print "Total time (last - first) = $totalTimeTime s\n";

  print "Registered (header) values: lap time: $edge_LapTime "
    . "cadence: $edge_LapCadence lap distance (m): $edge_LapDist\n";
  
  ## reset values ## ## ## 
  $grand_total_time_idle += $total_time_idle; 
  $grand_total_time_cycled  += $total_time_cycled ;
  $grand_total_cycles += $total_cycles ;
  $grand_total_Dist +=  $edge_LapDist;

  $total_time_idle = $total_time_cycled = $total_cycles = 0 ;
  $prev_Time = -1; 
  $parsingTrack ='N';
  $regCadence = 'N';
}

} ##/while

## Grand Totals:
$trackNo--;
$grand_total_Time = $grand_total_time_idle + $grand_total_time_cycled;

print "====== Totals/means for $trackNo tracks =====\n";
printf "Time = Idle: %d s Spinning: %d s Total: %d s\n", $grand_total_time_idle,
      $grand_total_time_cycled, $grand_total_Time;
   printf "Time = Idle: %.2f%% Spinning: %.2f%% Total: %.2f%%\n",
      $grand_total_time_idle/$grand_total_Time *100,
      $grand_total_time_cycled/$grand_total_Time * 100, 
      $grand_total_Time/$grand_total_Time *100;
print "Rotations (total) = $grand_total_cycles\n";
print "Mean cadence (computed) = " . $grand_total_cycles/$grand_total_time_cycled * 60 .  "\n";
print "Total distance (registered): $grand_total_Dist (m)\n";

## ### ### ### ### ###

sub xmlEleValue {
  my $en = shift; # element name
  my $el = shift; # line

  $el =~ /<$en>(.*)<\/$en>/;

  return "$1";

}

Przykładowy wydruk dla pliku fit/tcx zawierającego trzy segmenty:

$ cadencecalc.pl 2017-08-31.tcx
### Parsing track #1...
Time = Idle: 552 s Spinning: 2082 s Total: 2634 s
Time = Idle: 20.96% Spinning: 79.04% Total: 100.00%
Rotations (total) = 2684.95
Mean cadence (computed) = 77.3760806916427
Total time (last - first) = 2634 s
Registered (header) values: lap time: 2438.06 cadence: 77 lap distance (m): 16339.2
### Parsing track #2...
Time = Idle: 80 s Spinning: 652 s Total: 732 s
Time = Idle: 10.93% Spinning: 89.07% Total: 100.00%
Rotations (total) = 860.716666666666
Mean cadence (computed) = 79.2070552147239
Total time (last - first) = 3366 s
Registered (header) values: lap time: 731.05 cadence: 79 lap distance (m): 4994.82
### Parsing track #3...
Time = Idle: 29 s Spinning: 105 s Total: 134 s
Time = Idle: 21.64% Spinning: 78.36% Total: 100.00%
Rotations (total) = 120.716666666667
Mean cadence (computed) = 68.9809523809524
Total time (last - first) = 3500 s
Registered (header) values: lap time: 134.378 cadence: 69 lap distance (m): 761.78
====== Totals/means for 3 tracks =====
Time = Idle: 661 s Spinning: 2839 s Total: 3500 s
Time = Idle: 18.89% Spinning: 81.11% Total: 100.00%
Rotations (total) = 3666.38333333333
Mean cadence (computed) = 77.4860866502289
Total distance (registered): 22095.8 (m)

Podając jako minimalną prędkość 9 km/h otrzymamy:

$ cadencecalc.pl -s 9 2017-08-31.tcx
*** Segments with speed below 9 kmh skipped ***
### Parsing track #1...
Time = Idle: 654 s Spinning: 1980 s Total: 2634 s
Time = Idle: 24.83% Spinning: 75.17% Total: 100.00%
Rotations (total) = 2582.11666666667
Mean cadence (computed) = 78.2459595959596
Total time (last - first) = 2634 s
Registered (header) values: lap time: 2438.06 cadence: 77 lap distance (m): 16339.2
### Parsing track #2...
Time = Idle: 80 s Spinning: 652 s Total: 732 s
Time = Idle: 10.93% Spinning: 89.07% Total: 100.00%
Rotations (total) = 860.716666666666
Mean cadence (computed) = 79.2070552147239
Total time (last - first) = 3366 s
Registered (header) values: lap time: 731.05 cadence: 79 lap distance (m): 4994.82
### Parsing track #3...
Time = Idle: 29 s Spinning: 105 s Total: 134 s
Time = Idle: 21.64% Spinning: 78.36% Total: 100.00%
Rotations (total) = 120.716666666667
Mean cadence (computed) = 68.9809523809524
Total time (last - first) = 3500 s
Registered (header) values: lap time: 134.378 cadence: 69 lap distance (m): 761.78
====== Totals/means for 3 tracks =====
Time = Idle: 763 s Spinning: 2737 s Total: 3500 s
Time = Idle: 21.80% Spinning: 78.20% Total: 100.00%
Rotations (total) = 3563.55
Mean cadence (computed) = 78.1194738765071
Total distance (registered): 22095.8 (m)

Idle oznacza czas w którym nie kręcimy i/lub jedziemy poniżej prędkości minimalnej (podawany jest czas w sekundach i udział w całości). Rotations to liczba obrotów. Obliczone wartości wyglądają na prawidłowe na co wskazywałoby, że są bliskie wartościom liczonym przez Garmina.

poniedziałek, 4 września 2017

Wycieczka na Słowację i do Budapesztu

Pojechaliśmy na wycieczkę na Słowację i na Węgry. Dwa dni zwiedzania okolic Starej Lubowli (Stará Ľubovňa) potem 2 dni w Budapeszcie. Z dojazdami wyszło od poniedziałku do niedzieli 21--27 sierpnia 2017, tj. przyjechaliśmy do Lubowli w poniedziałek około 20:00, a w niedzielę z kolei byliśmy w domu około 18:00 (wyjeżdżając z Budapesztu przed 7:00 rano).

Udało mi się mimo niechętnej postawy małżonki zabrać rower. Żeby było więcej miejsca w bagażniku na bagaże, to z kół zdjąłem zaciski i wsadziłem je do zrobionych z kartonu pokrowców. Ponadto odkręciłem pedały. Po tych zabiegach rower był bardziej płaski i stwarzał lepsze wrażenie (na małżonce, bo pewnie i bez odkręcania cały bagaż też by się zmieścił). Czy ten rower w ogóle się przyda nie był całkiem pewne -- zależało to m.in. od zakwaterowania.

Pierwszego dnia w Lubowli zwiedzaliśmy głównie zamek. Interesujące miejsce, dużo poloników (tj. przedmiotów związanych z Polską) i ciekawe ekspozycje, w szczególności rekonstrukcje warsztatów rzemieślniczych, browaru i gorzelni. Pokaz ptaków drapieżnych używanych do polowań -- dla mnie taka sobie atrakcja, ale publiczność była liczna i zachwycona. Po zamku pora na zwiedzanie skansenu, który jest w pobliżu (można kupić bilet od razu uprawniający do wejścia do zamku i do skansenu.) Też miejsce warte zwiedzania, w przeciwieństwie do następnej atrakcji pn. średniowieczny obóz wojskowy (Stredoveký vojenský tábor -- w skrócie tabor), którą spokojnie można sobie odpuścić -- oszczędzając 2 EUR. Niewiele jest tu ciekawych rzeczy do oglądania; konkretnie mówiąc są cztery: replika wozu husyckiego (wóz taborowy) z okresu wojen husyckich i trzy rodzaje katapult. Nawet interesujące te katapulty, ale zwiedzanie wszystkiego zajęło nam góra 10 minut, czyli nie za dużo. Podobno jest to miejsce imprez plenerowych typu turnieje rycerskie czy łucznicze, ale my nie mieliśmy widocznie szczęścia bo nic takiego nie miało miejsca, a gdyby nawet to są to raczej atrakcje dla dzieci. Jest też `stylizowana karczma', pytanie tylko na co stylizowana? Wygląd nie zachęcał do wejścia.

Wieczorem pojechaliśmy na basen do Wyżnych Rużbachów (Vyšné Ružbachy). Kąpielisko termalne Izabela (chodzi o hrabiankę Zamojską BTW, która w pełnym brzmieniu nazywała się Izabela Alfonsina Maria Teresa Antonina Krystyna Mercedes Karolina Adelajda Rafaela de Burbon -- tutaj zwana w skrócie grófka Isabela) Basen otwarty był zamknięty, bo cośtam, ale czynny był ten całoroczny (czyli znajdujący się w budynku -- wejście pod recepcją hotelu Strand). Ja nie miałem slipów, to nie wszedłem, Elka z Jankiem pływali a ja poszedłem na kawę latte i ciasto do Hotelu (b. dobre i w przystępnej cenie). Elka wykąpała się też odważnie w słynnym (jeziorku kraterowym (trawertynowym) -- drugiej obok basenów termalnych atrakcji (ignorując zakaz kąpieli).

Drugiego dnia zwiedzanie okolicy: Czerwony klasztor (Červený kláštor), potem spacer wzdłuż Dunajca do kładki do Sromowic. Dunajcem nie płynęliśmy, podobno drogo i ciężko się dopchać takie kolejki. Po obiedzie zameczek w Strážkach koło Białej Spiskiej. Znajduje się tam kolekcja obrazów Ladislava Medňanskiego, co akurat dla mnie nie jest wielką atrakcją -- no nie znam się na malarstwie i zwiedzanie galerii zwykle mnie nudzi. Po Strážkach zwiedzanie miejscowości Kieżmark (Kežmarok)--zamek i spacer po starym mieście.

Zakwaterowani byliśmy komfortowo w czymś w rodzaju internatu (dzięki znajomej małżonki, na zaproszenie której zresztą pojechaliśmy). Mieliśmy do wyłącznej dyspozycji 5 pokoi, kuchnię z jadalnią i łazienkę. Dyrektorski apartament!

W związku z tym rower też nikomu nie przeszkadzał -- parkował w jadalni -- i dwa razy się przejechałem po okolicy. Żeby się nie alienować od reszty rodziny rowerowałem przed śniadaniem, tj. zaczynałem około 6 rano. Się okazało, że rano to tu całkiem zimno jest, np. drugiego dnia było 8C (pierwszego było ciut cieplej), a ja w krótkich spodniach, bez rękawic i czapki -- bo tak sobie wymyśliłem, że przecież jedziemy na południe. Ale dałem radę...

Budapeszt

W czwartek rano pojechaliśmy do Budapesztu, po drodze odwiedzając termalne baseny jaskiniowe w Miszkolcu-Tapolcy. Do Budapesztu dotarliśmy przed 19:00. Tym razem kwaterą było w miarę małe ale wygodne, czyste i nowocześnie wyposażone mieszkanie w bloku, przy ulicy Törökugrató (wyszukane przez AirBNB.) Ulica Törökugrató BTW to Buda a nie Peszt, co też się okazało szczęśliwe z punktu widzenia rowerowania. Buda bowiem jest górzysta, a ulica Törökugrató jest już poza centrum. Dało radę zatem całkiem serio pojeździć, co by w centrum zupełnie nieznanego miasta było raczej niemożliwe. W szczególności pierwszego dnia wjechałem na górkę pn Széchenyi-hegy, z nachyleniami sięgającymi 15%.

Część oficjalna obejmowała zwiedzanie tego co należy zwiedzać w Budapeszcie: dwa zamki, dwa kościoły (Stefana i Macieja), targ, operę, mosty, no i synagogę. W niedzielę przed siódmą rozpoczęliśmy odwrót, w domu byliśmy około 17:30. Warunki do jazdy były prawie że idealne--zero ruchu, tylko trochę popadało w okolicach Kujaw.

Zdjęcia z wycieczki są tutaj.

piątek, 11 sierpnia 2017

Wycieczka do Suwałk 2017

Byliśmy od czwartku 3.08 do poniedziałku 7.08. Niezwykle udany wyjazd: pogoda super, dwa spływy (24km po Czarnej Hańczy oraz 14km po Rospudzie), i zwiedzanie okolicy. Ja do tego jeździłem codziennie na rowerze zaliczając następujące trasy: Elbląg--Górowo Iławieckie (przez Pasłęk/Pieniężno), Suwałki--Sejny, Suwałki--Buda Ruska, Suwałki--Hańcza (wokół jeziora Hańcza), Suwałki--Buda Ruska raz jeszcze. Razem rowerowania wyszło około 95 + 50 + 50 + 80 + 40 = 320 km czyli Not bad. Do tego spotkanie z przyjaciółmi jeszcze ze studiów, u których się zatrzymaliśmy zresztą. Teraz mam trochę zdjęć i filmów, które wymagają obróbki. Zdjęcia były robione albo smarfonem z włączonym trybem lokalizacji (czyli w trybie dopisywania współrzędnych geograficznych) albo aparatem bez GPSa. W tym drugim przypadku współrzędne dodaję w ,,standardowy'' sposób: synchronizuję ze śladem GPX (z Garmina Legenda, który robił za loggera na wycieczkach.)

Oczywiście nie ma tak, że wszystko poszło od pierwszego strzału. W szczególności smartfon to jeszcze nie opanowana do końca technologia:-) (Mam go od jesieni ub.r.)

Problem #1: jak skopiować zdjęcia na PC?

Kopiowanie zdjęć na kartę. Smartfon Redmi Note3.

W Fedorze21/Xfce (w Gnome działa) nie działa łącze Android-PC (simple-mtpfs). Należy:

vi /etc/udev/rules.d/10-phone.rules
# wpisać:
SUBSYSTEM=="usb", ATTR{idVendor}=="2717", ATTR{idProduct}=="ff40",\
SYMLINK="redminote"

# Make sure to replace the ATTR{idVendor} and ATTR{idProduct} values
# with the one you got from the dmesg | tail command, and the SYMLINK
# value with whatever you want - it will be the name of the symbolic
# link udev will create in your /dev folder, pointing to your device.
# http://nknu.net/mount-nexus5-on-fedora23-using-simple-mtpfs/

# reload udev rules (as root):
udevadm control --reload-rules

mkdir /tmp/redminote
simple-mtpfs /dev/redminote /tmp/redminote
# odmontowanie BTW:
# fusermount -u /tmp/redminote

Kopiowanie plików ze zdjęciami na kartę mikro SDHC w RedmiNote nie jest oczywiste. Znalazłem taki oto sposób: Explorer→Obrazy (albo Gallery), przesuwam do ostatniego obrazu. (Jeżeli wybiorę wcześniejsze zdjęcie, to nie ma gwarancji, że skopiuje się wszystko--opcja `zaznacz wszystko' jakoś tak kulawo działa.) Naciskam i przytrzymuję (w ten sposób zaznaczam). Po zaznaczeniu pojawia się `zaznacz wszystko', które wybieram. Na dole pojawia się wtedy menu, z którego wybieram pozycję `Więcej', a następnie `Kopiuj'.

Po skopiowaniu na kartę usunąłem zdjęcia z pamięci aparatu: Gallery→Delete (po zaznaczeniu zdjęć do usunięcia lub wybraniu `zaznacz wszystko')

Problem #2: dokładność współrzędnych w zdjęciach ze smatfona.

Dokładność pomiaru GPSa

Zauważyłem przypadkowo, że czasami dokładność wstawianych współrzędnych jest kiepska, ale nie wiem co jest tego przyczyną. Przypuszczam jedynie, że jeżeli urządzenie nie potrafi ustalić pozycji za pomocą odbiornika GPS, to używa jakiś grubych przybliżeń. Ciekawe zatem jakie informacje oprócz długości/szerokości geograficznej są zapisywane w pliku JPG (może jest informacje na temat dokładności?):

## wszystkie tagi EXIF dotyczące GPSa (mogą być inne oprócz EXIF):
exiftool -gps:all IMG_20170803_120608.jpg

## albo
exiftool -All IMG_20170803_120608.jpg | grep -i GPS

Wypisuje różne rzeczy ale nic na temat dokładności.

Wynik jest zatem niekonkluzywny z punktu widzenia problemu.

BTW: Ustalanie współrzędnych GPS może być ustawione na trzy sposoby: wysoka dokładność (GPS + WiFi/sieci komórkowe), tylko GPS, tylko WiFi/sieci komórkowe. Ja mam ustawiony na wysoką dokładność. Być może ustawienie na `tylko GPS' da w rezultacie taki efekt, że albo zdjęcia będą tagowane w miarę dokładnie albo wcale? Jeszcze tego nie sprawdzałem.

Różne rzeczy

Przy okazji testowania potrzebowałem utworzyć plik GPX zawierający współrzędne punktów--zdjęć wykonanych w jednym miejscu. Taki plik łatwo utworzyć korzystając z exiftool-a:

## wypisanie współrzędnych w formacie decymalnym
exiftool -n -T -gpslatitude -gpslongitude  IMG_20170805_135232.jpg
54.0761200833333	23.0741937777778

## wypisanie współrzędnych dla wszystkich plików:
## opcja -T pomija nazwę pliku
exiftool -n -gpslatitude -gpslongitude  IMG_20170805_135232.jpg

## albo
for i in *.jpg ; do
echo $i `exiftool -n -T -gpslatitude -gpslongitude $i` ; done
## albo od razu minimalistyczny plik GPX:
echo '<?xml version="1.0" encoding="UTF-8"?>' > PLIK.gpx
echo '<gpx version="1.0" xmlns="http://www.topografix.com/GPX/1/0">' >> PLIK.gpx

for i in *.jpg ; do
echo $i `exiftool -n -T -gpslatitude -gpslongitude $i`| \
awk '{print "<wpt lat=\"" $2 "\" lon=\"" $3 "\"><name>" \
$1 "</name></wpt>"  }' > PLIK.gpx; done

echo '</gpx>' >> PLIK.gpx

# Jeżeli nie zależy nam na formacie GPX
#http://u88.n24.queensu.ca/exiftool/forum/index.php?topic=3075.0
exiftool -n -filename -gpslatitude -gpslongitude -T DIR > out.txt

Tu jest na przykład plik z informacją o współrzędnych ze zdjęć wykonanych w restauracji ,,Gospoda pod Sieją'' w Starym Folwarku. Jedno ze zdjęć (pierwsze tam wykonane) ma beznadziejnie duży błąd lokalizacji. Podobnie na zdjęciach wykonanych na spływie Rospudą jest kilka ze znaczącym błędem.

wtorek, 25 lipca 2017

Wycieczka do Ostródy

Do Stębarka (niem. Tannenberg) czyli na pole bitwy pod Grunwaldem 1410. Od wielu lat odbywa się tam rekonstrukcja. Postanowiłem obejrzeć. Pojechałem z Jankiem.

Pierwsza trudność kwatera: rekonstrukcja bitwy to nadzwyczajne wydarzenie. Okolica jest nieprzystosowania do takiej liczby gości na raz. W rezultacie udało nam się zarezerwować kwaterę aż pod Ostródą (37 km od pola bitwy), co miało swoje plusy i minusy. Plusy: super-fajna, godna polecenia kwatera pn. Agroturystyka nad Szelągiem. BTW Szeląg Wlk. to jezioro. My byliśmy w Zwierzewie a po drugiej stronie jeziora są słynne Stare Jabłonki (Karol Okrasa, którego programy lubię) i słynny Hotel Anders. Minusy: daleko (w rezultacie Janek wymiękł w kluczowym momencie)

Plan był taki: czwartek -- dojazd; piątek -- oglądamy próbę bitwy; sobota -- oglądamy bitwę; niedziela -- wyjeżdżamy. Z realizacją było zaś tak, że Janek PKPem podjechał do Ostródy a ja rowerem z Sopotu przez Kieżmark, Malbork, Dzieżgoń, Małdyty. Zasiedziałem się w domu i wyjechałem w rezultacie 12:40. Trochę na styk, żeby przed nocą zdążyć, ale dało radę głównie dzięki silnemu wiatrowi w plecy. Za Małdytami wjechałem w dawną drogę Warszawa-Gdańsk. Teraz praktycznie nieużywana--luksusowa ścieżka rowerowa. W drodze powrotnej jechałem nią nawet dalej--do Pasłęka.

Dzień drugi: rano do Ostródy, krótkie zwiedzanie miasta (zamek); potem rozglądamy się za obiadem. Ja lubię chińskie jedzenie, więc idziemy do Chińczyka (Bistro pn GONG JI). Było dużo gości to fakt, ale były też wolne miejsca. Pytamy ile potrwa podanie: 40 minut. Nie ma czegoś na szybko, jakaś zupa? Nie ma. Wszystko za 40 minut. Dajemy sobie spokój--jemy zupę pomidorową + pstrąga z frytkami w restauracji La Luna. Aha u Chińczyka był pani Gessler -- której nie znoszę.

Jesteśmy około 15 na polu bitwy. Robimy trochę zdjęć. Sama próba IMO to pomyłka i szkoda czasu. Ma się tak do prawdziwej imprezy jak przysłowiowa pięść do nosa. Wracamy--Janek jest padnięty.

Sobota: Janek ma dość i nie jedzie. Ja jadę: impreza jest wystrzałowa. Oczywiście inscenizacja bitwy to (sienkiewiczowska) lipa, do tego z konieczności odtworzona w wersji spieszonej (koni tylko 30--40, no bo to kosztuje) ale fajnie popatrzeć na ten wielotysięczny tłum. Dałem dupy oczywiście. Nie wziąłem statywu, kręciłem film i robiłem zdjęcia jednocześnie. Warto mieć statyw i kija do selfie (do zdjęć/filmów znad głowy), bo ludzi multum i zasłaniają.

Niedziela powrót. Teraz z kolei ja jest lekko padnięty: w nogach 180 plus 190 km = 370 w trzy dni. No ale jadę, do tego uparłem się że przez Frombork (planowane jest 215km). Niestety to nie był mój dzień--dojechałem tylko za Elbląg, do Starego Pola. Tam wsiadłem do pociągu relacji Elbląg--Gdynia.

Zdjęcia z wycieczki są tutaj. Ślady zaś tutaj: #dzień1, #dzień2, #dzień3, #dzień4. Zrobiłem też parę filmików--do odszukania na moim kanale na YT.

Kajakiem po Gdańsku

Płynęliśmy w niedzielę 23 lipca 2017. Fajna imprezka -- dwie godziny pływania wokół wysp: Spichrzów i Ołowianki, w okazyjnej cenie 35 PLN/osoba. Ślad naszej wycieczki jest tutaj albo na Endomondo.

No więc Gdańsk także od strony wody wygląda impressive. A mam porównanie bo kiedyś trenowałem wiosła i pływałem po okolicy. Nic wtedy nie było, a teraz wybrzeża zagospodarowane, moc turystów + usług dla nich (kajaki, łodzie, motorówki, stateczki, statki, jachty duże i małe w Marinie). Kładka -- na którą niektórzy psy wieszają -- też fajnie wygląda (widziałem pierwszy raz)... Pogodę mieliśmy optymalną. Wybieramy się raz jeszcze: bez przewodnika po Opływie Motławy (wzdłuż umocnień od strony Żuław)

Tak przy okazji są to takie niekoniecznie popularne atrakcje Gdańska/Trójmiasta (okolic trójmiasta +/- 100km), które okazują się ciekawsze niż te słynne i znane. Moja lista zawiera (porządek dowolny):

Dolina Radości (skocznia narciarska, bar rybny Rybakówka); jeżeli rowerem (pożyczonym), to można się przejechać do sankturaium w Matemblewie a nawet jeszcz kawałek dalej (staw Wróbla) z grilem i tam się rozbić na popas.

Kajakiem (no to wiadomo, bo tego dotyczy ten wpis) po Motławie.

Muzeum wsi pomorskiej (przy okazji zwiedzania katedry w Gdańsku-Oliwie) w spichrzu Opackim (wystawa stała, por. oddział etnografii).

W Sopocie nic nie ma:-)

W Gdyni muzeum Marynarki Wojennej (jeżeli kogoś interesują militaria) dużo ciekawsze niż to dziadostwo za 500 mln w Gdańsku oraz Muzeum Emigracji.

Zamiast jechać oglądać wydmy w Łebie pojechać ciut dalej do Smołdzina/Kluk(ów). Tam też są wydmy, a oprócz tego skansen we wsi Kluki -- pozostałość po unikatowej nieistniejącej już społeczności, która utrzymywała się z łapania ryb na jeziorach Łebsko/Gardno, tworząc tutaj unikatowy mikrokosmos (z uwagi na otaczające ją wody i bagna wieś była mocno izolowana).

Kwidzyn gdzie należy obejrzeć katedrę, muzeum Powiśla oraz kryptę Wielkich Mistrzów. Malbork to wielka kupa cegieł i tyle, w środku tej kupy nic prawie nie ma. Kwidzyn to dużo mniejsza kupa cegieł, ale za to multum ciekawych eksponatów w katedrze i muzeum... Jadąc do Kwidzyna (nie Kwidzynia) można oglądać pozostałości po Olendrach--mniejszości holenderskich mennonitów (konstrukcje hydrotechniczne w Piekle/Białej Górze, cmentarze z oryginalnymi nagrobkami https://pl.wikipedia.org/wiki/Ol%C4%99drzy).

No i tyle na razie.

poniedziałek, 12 czerwca 2017

Stacja pogodowa WS1080

Zakupiłem używaną (z przeznaczeniem do rejestrowania parametrów pogody w innym miejscu BTW -- nie żebym chciał używać dwie różne stacje na raz w tym samym miejscu). Ponieważ akurat pod ręką był c.h.i.p (aka the world's first 9USD computer), podłączyłem na razie stację do chipa.

chip@chip:~/Crontab$ lsusb 
Bus 002 Device 003: ID 1941:8021 Dream Link WH1080 \
 Weather Station / USB Missile Launcher

root@chip:~# apt-get update 
root@chip:~# apt-get install python-pip
root@chip:~# pip install pywws
...
Successfully installed pywws tzlocal pytz
Cleaning up...
root@chip:~# pywws-hourly -v /home/chip/Logs/weather\
  >> /home/chip/Logs/weather/Hourly.log
cat /home/chip/Logs/weather/Hourly.log
Unknown weather station type. Please edit weather.ini
and set 'ws type' to '1080' or '3080', as appropriate.
Your station is probably a '1080' type.

# wpisać 1080 w weather.ini
# zmienić wpis dotyczący /tmp/weather w weather.ini

root@chip:~/Crontab#  pywws-hourly -v /home/chip/Logs/weather\
 >> /home/chip/Logs/weather/Hourly.log
03:07:00:pywws.Logger:pywws version 16.12.0, build 1367 (e917ba9)
03:07:00:pywws.Logger:Python version 2.7.9 (default, Mar  1 2015, 13:48:22) 
[GCC 4.9.2]
03:07:00:pywws.WeatherStation.CUSBDrive:using pywws.device_libusb1
03:07:02:pywws.DataLogger:Synchronising to weather station
03:09:00:pywws.weather_station:live_data missed
03:09:44:pywws.DataLogger:Fetching data
03:09:45:pywws.Process:Generating summary data
03:09:45:pywws.Calib:Using default calibration

I działa...

środa, 7 czerwca 2017

Podsumowania rowerowe 200 tys/7 tys

Jeszcze się nie skończył czerwiec a ja już nabiłem rekordowe 7 tysięcy kilometrów przejechanego rocznego dystansu (4 czerwca dokładnie to się stało). Do tej pory mój rekord to było 6 tys na koniec czerwca, teraz wygląd, że będzie z łatwością osiem.

Nawiasem mówiąc 24 maja osiągnąłem 200 tys na liczniku życiowego dystansu (może da się dociągnąć do 250 tys?).

Z tej okazji podsumowałem mój życiowy dystans (bez lat 1992--1991, dla których nie mam detalicznych danych) z podziałem na pierwsze/drugie półrocze. Wyniki są następujące:

----------------------------------------------------
kwartał km    %%      |  kwartał km    %%     razem%
----------------------------------------------------
1993_1  2330  44.13   |  1993_2  2950  55.87  100.00
1994_1  2805  62.06   |  1994_2  1715  37.94  100.00
1995_1  1710  47.90   |  1995_2  1860  52.10  100.00
1996_1  1546  33.90   |  1996_2  3014  66.10  100.00
1997_1  2055  40.73   |  1997_2  2990  59.27  100.00
1998_1  2530  38.13   |  1998_2  4105  61.87  100.00
1999_1  3065  47.63   |  1999_2  3370  52.37  100.00
2000_1  4910  43.82   |  2000_2  6295  56.18  100.00
2001_1  5255  48.86   |  2001_2  5500  51.14  100.00
2002_1  6240  59.68   |  2002_2  4215  40.32  100.00
2003_1  5130  48.72   |  2003_2  5400  51.28  100.00
2004_1  3575  41.16   |  2004_2  5110  58.84  100.00
2005_1  4415  49.33   |  2005_2  4535  50.67  100.00
2006_1  0000   0.00   |  2006_2  2880 100.00  100.00
2007_1  1855  46.73   |  2007_2  2115  53.27  100.00
2008_1  2380  36.12   |  2008_2  4210  63.88  100.00
2009_1  2535  45.97   |  2009_2  2980  54.03  100.00
2010_1  3060  47.81   |  2010_2  3340  52.19  100.00
2011_1  3535  43.45   |  2011_2  4600  56.55  100.00
2012_1  3285  45.44   |  2012_2  3945  54.56  100.00
2013_1  3710  45.13   |  2013_2  4510  54.87  100.00
2014_1  4020  54.55   |  2014_2  3350  45.45  100.00
2015_1  4100  46.80   |  2015_2  4660  53.20  100.00
2016_1  5365  47.80   |  2016_2  5860  52.20  100.00
2017_1  7155 100.00   |  2017_2  0000   0.00  100.00
----------------------------------------------------
Średnio: kw1 = 46.63 kw2 = 53.37 razem% = 100.00 (25 lat)
Razem: 200835.00

Zawsze mi się wydawało, że w drugim półroczu przejeżdżam mniej a tu proszę--faktycznie jest dokładnie odwrotnie.

czwartek, 1 czerwca 2017

Publikowanie z bazy danych

Absolutnie minimalistyczny przykład wykorzystania LaTeXa do publikowania zawartości bazy danych:

1. Dane są w bazie sqlite (można ją utworzyć/dodawać rekordy w prosty sposób wykorzystując coś co się nazywa sqlitebrowser)

W przykładzie (poniżej) plik kleinertest.db3 zawiera tabelę Kursanci, z której pobierane są pola ImieNazwisko, PlecOcena.

2. Do drukowania uruchamiamy skrypt w języku Perl. Skrypt jest tak prosty że do dopasowania go do konkretnej tabeli nie potrzeba znajomości Perla a wystarczy zdrowy rozsądek (co zmienić zaznaczono @@)

Perl dla Windows do pobrania z https://www.activestate.com/

3. Skrypt uruchamia pdflatexa i drukuje zawartość bazy do pliku pdf

4. Można skomplikować skrypt, np podając argument na wejściu. Dajmy na to nazwisko delikwenta do wydrukowania. Żeby nie drukować wszystkiego. Do tego potrzeba minimalnej znajomości Perla

#!/usr/bin/perl -w
# Potrzebne są moduły Perla DBI DBD-SQLite DBD-SQLite2
#
use strict;
use utf8;
use DBI;

binmode(STDOUT, ":utf8");

my $dbfileName= "kleinertest.db3"; ## @@ nazwa pliku z bazą
my $tmpfileName = "kleinertest.tex"; ## @@ nazwa pliku .tex
my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfileName", "", "");

## @@ Pobranie danych z tabeli Kursanci (pola: ImieNazwisko, Plec Ocena)
my $sth = $dbh->prepare("SELECT
   ImieNazwisko,
   Plec,
   Ocena
   FROM Kursanci ");
$sth ->execute();

## PreAmBuła ### ### ### ### ###
open (TEX, ">$tmpfileName");

print TEX "\\documentclass{article}\\usepackage{mydbiprint}\\begin{document}\n";

## MidBuła: drukowanie rekordów z bazy ## ### ### ###
## ImieNazwisko = $r[0], Plec = $r[1], Ocena = $r[2] itd...
while ( my @r = $sth->fetchrow_array() ) {
     print TEX "\\Dyplom{ $r[0] }{$r[1]}{ $r[2] }\n"; ## @@ dopasować do konkretnej tabeli
   }

## PostAmBuła ## ### ### ### ###
print TEX "\\end{document}\n";

$dbh->disconnect || warn "Nie moge zamknac bazy $dbfileName\n";

## TeXowanie pliku: ## ## ### ### ### ### ###
close(TEX);
system("pdflatex", "$tmpfileName");

## koniec 

Przykładowy pakiet mydbiprint.sty:

%% Minimalistyczny szablon do drukowania z bazy
\RequirePackage[utf8]{inputenc}
\RequirePackage{polski}
\RequirePackage{ifthen}
\pagestyle{empty}
\newcommand{\Dyplom}[3]{%%
  \begin{center}\fontsize{30}{40}\selectfont DYPLOM\end{center}
    \ifthenelse{\equal{#2}{K}}
               {\DyplomDlaPani{#1}{#3}}
               {\DyplomDlaPana{#1}{#3}}
 }
\newcommand\DyplomDlaPani[2]{%
   \begin{center}Pani #1\end{center}
  Zdała egzamin z oceną #2\newpage}
\newcommand\DyplomDlaPana[2]{\begin{center}Pan #1\end{center}
    Zdał egzamin z oceną #2\newpage}
\endinput 

poniedziałek, 15 maja 2017

Jak się robi propagandę na przykładzie problemu tzw. uchodźców

Przewodniczący Schetyna zmieniając zdanie o 180 stopni w/s przyjmowania do Polski emigrantów zaskoczył. Obserwuje się szok-oburzenie-niedowierzania po stronie oświeconego-liberalizmu a sam przewodniczący zaś tłumaczy się pokrętnie i kluczy.

Trzy stanowiska można wyróżnić w sprawie: oświecony-liberalizm oczywiście jest za i w każdej liczbie; "antyterroryści" straszą, że przyjadą zwolennicy ISIS i absolutnie są przeciw; zdroworozsądkowcy uważają, że nie należy pomogać w ten sposób, bo to jest sposób wysoce nieefektywny. Pierwsze dwa stanowiska to demagogia -- jeszcze nie widziałem sensownych argumentów za (wszystko opiera się na wierze, "wartościach" i uczuciach). Nie dziwi w związku z tym, że oświeceni chętnie polemizują z antyterrorystami, ale już z zwolennikami zdrowego rozsądku nigdy.

Wywiad z "politolożką" w politruka.pl (niezbędnika każdego yntyligęta), jest przykładem takiej typowej topornej propagandy. Tekst za zrzucie z ekranu moje komentarz poniżej:

0. Tekst ma stwarzać wrażenie, że jest wysoce naukowy (słowo NAUKA pojawia się tam co chwila jako synonim słowa prawda--znany chwyt mający ustawić na baczność czytelników: my naukowcy vs ciemniaki bez tytułów naukowych z kruchty)

1. Teza na początek "należy ich brać" i w tym celu otworzyć granice (nie czy w ogóle albo czy są lepsze sposoby pomocy -- nie myśleć brać)

2. Jest ich mało a pensje wszystkich rosną (naukowo udowodnione-twierdzi pani politolożka :-). Jednym słowem nie ma się czego bać bo zawsze tak było a korzyści są ogromne...

3. Nie ma sensu rozróżniać uchodźców i emigrantów, brać wszystkich, którzy tu lezą (no to niestety słabo naukowo udowodnione; wręcz można powiedzieć, że to jest nieprawda)

4. Na pytanie o politykę integracyjną pani zauważa że obcy są ciągle second-class-citizens, a żeby to zmienić "potrzebne są instytucje" -- niezwykle głęboka analiza jednym słowem... Pytanie ile te instytucje by kosztowały podatnika nie pada...

5. "Inwestując w Afryce stymulujemy migrację"--bo migrują lepiej wykształceni/bogatsi. Wg pani "naukowczyni" pomoc na miejscu stymuluje migracje a brak pomocy nie stymuluje. A może jednak też stymuluje i to bardziej? Kto dajmy na to chciałby żyć w kraju gdzie nie ma opieki medycznej na przykład (ponieważ wszyscy lekarze są w Europie). Idiotka o "lewicowej wrażliwości", ale neokolonialnym ptasim mózgu no nie pomyślała...

Cały ten tekst jest w istocie jednym wielkim manifestem neokolonialnej mentalności: ch#j tę babę obchodzi Afryka, mogą tam umierać z głodu, ważny jest tylko Europejski rynek pracy, na którym płace rosną, a ludziom żyje się lepiej... Pytanie o to jakie perspektywy ma kraj, z którego wyjeżdżają najlepsi, a im bardziej im się ten wyjazd ułatwi tym ich więcej wyjedzie -- oczywiście nie pada...

6. "Nie mogę nikomu mówić co ma robić", ale jestem pewna, że należy otworzyć granice -- He, he do tej pory było--jak to u oświeconych liberałów, super-naukowo a tu klops, teza z tytułu kompletnie z czapki vel z dupy (ludzie znajdą sposoby itp... co ciekawe akurat ci z dżungli pod Calais jakoś nie mogli znaleźć -- i wegetowali tam całymi latami -- PECH, jakieś wyjątkowe przymułysię trafiły w rodzinnym kraju pani naukowczyni)