sobota, 24 stycznia 2015

Kolorowy pasek na zadaną długość

Oto prosty kod LaTeXa, który ma w zamierzeniu spowodować wydrukowanie kolorowego paska o długości 44mm:


Rys: rudy pasek

\documentclass{article}
\usepackage{graphicx,color}
\begin{document}
\definecolor{Xrudy}{rgb}{0.8,0.34,0.0}
\colorbox{Xrudy}{\strut\vrule width44mm height1pt}
\end{document}

Niestety kolorowy pasek wcale nie jest długi na 44mm tylko dłuższy (co widać na rysunku obok: rudy pasek jest dłuższy od czarnej kreski, która faktycznie ma 44mm).

Konsultacja z dokumentacją wyjaśnia, że LaTeX dokłada pewne rzeczy od siebie:


\documentclass{article}
\usepackage{graphicx,color}
\begin{document}
\showthe\fboxrule %% wyświetl wartość parametru \fboxrule
\showthe\fboxsep %% wyświetl wartość parametru \fboxsep
\end{document}

Każde \showthe\parametr powoduje że LaTeX, zatrzymuje kompilację wyświetlając na ekranie wartość parametru (aby kontynuować kompilację należy nacisnąć klawisza ENTER):


> 0.4pt.
l.31 \showthe\fboxrule

?
> 3.0pt.
l.32 \showthe\fboxsep

Czyli ramka ma domyślą grubość 0,4pt a margines wewnętrzny jest szeroki na 3,0 pt.

Aby się pozbyć dodatkowych odstępów należy zapodać:


\fboxsep=0pt

Można sprawdzić, że to faktycznie działa:


\documentclass{article}
\usepackage{graphicx,color}
\begin{document}
\definecolor{Xrudy}{rgb}{0.8,0.34,0.0}
\setbox0\hbox{% zapisujemy do pudełka zero żeby je potem zmierzyć
\colorbox{Xrudy}{\strut\vrule width44mm height1pt}}
\showthe\wd0 %% szerokość pudełka zero zdefiniowanego wyżej

\fboxsep=0pt
\setbox0\hbox{\colorbox{Xrudy}{\strut\vrule width44mm height1pt}}
\showthe\wd0
\end{document}

W rezultacie LaTeX wyświetli podczas kompilacji:


> 131.19212pt.
l.30 \showthe\wd0

?
> 125.19212pt.
l.36 \showthe\wd0

131,19212pt - 125,19212pt = 6,000 pt jak w mordę...

poniedziałek, 19 stycznia 2015

Cron i ostatni dzień miesiąca

Wprawdzie nie wiadomo który dzień jest ostatnim w miesiącu, ale na pewno po nim będzie dzień z numerem 1. Numer dnia, który będzie jutro można zaś ustalić wykorzystując date:


$ date +%d -d tomorrow
$ 19

W dniach 28--31, o godzinie 23:55 sprawdź czy następny dzień ma numer jeden. Jeżeli tak, wykonaj SKRYPT.sh:


55 23 28-31 * * [ "$(date +%d -d tomorrow)" = "01" ] && SKRYPT.sh

niedziela, 18 stycznia 2015

Google Maps brzydko kombinuje z formatem KML

Google wyświetla coś takiego kiedy oglądam mapę z ostatniego wyjazdu:

Jedna z funkcji Map Google używanych na tej stronie wkrótce się zmieni. Konieczne będzie przeniesienie zawartości niestandardowej mapy.

Klikam w Dowiedz się więcej:

Po lutym 2015 roku nie będzie już można wyświetlać niestandardowej zawartości plików KML w klasycznej wersji Map Google. KML to format pliku używany przez Google Earth do wymiany informacji geograficznych.

Dalej nie bardzo wiadomo w czym będzie problem, ale przynajmniej powiedzieli, że to już niedługo, jak przestanie działać. Jeszcze jeden klik i w końcu wiadomo o co chodzi (ale po angielsku):

From February 2015, maps created in the classic Google Maps -- https://maps.google.com/ -- will no longer load KML/KMZ files from external websites. However, we know that KML files are a really useful way to work with geographic data, so we've added KML to Google My Maps, and continue to support this format with other Google Maps APIs. We hope that one of these options will meet your needs.

A więc google zmienił zdanie. Kiedyś twierdził, że cyt: KML upload and rendering has always been problematic with Maps i że lepiej (jeżeli już), to nie importować KML tylko wyświetlić go podając URL do dokumentu KML jako wartość parametru q, przykładowo:

https://mapy.google.pl/maps?q=http://pinkaccordions.homelinux.org/PLIK.kml

A teraz że wręcz przeciwnie: parametr q w ogóle nie zadziała.

Wraz ze zmianą zdania trzeba przyznać poprawiono wsparcie dla KML w Google Maps -- teraz już nie jest problematic (sprawdziłem jest OK).

Google wreszcie ustalił, że można korzystać z Google Maps bez zakładania konta Google i podjął stosowne działania? Nieładnie.

Zatem trzeba będzie zmienić sposób w jakim są wyświetlane pliki KML na Google Maps (teraz to się nazywa zdaje się Moje Mapy/My Maps). Na szczęście nie jest tego w moim przypadku za dużo.

wtorek, 13 stycznia 2015

Sorry, Charlie Hebdo

It seems Charlie Hebdo massacre is a big surprise in France but what shock me even more is that the plain fact that France is at war with ISIS (cf French planes carry out air strikes on Isis targets in Iraq) was so efficiently obliterated from the awarness of the french populations, that the attack is met with naive incredulity and the reaction to it is so infantile.

The victims are presented now as defenders of freedom of speech which is not the case. They just produced stupid pictures, went to war with religion and (to their surprise) the religion retaliated. True free speach hero is (among many others) Norman Finkelstein who comments Charlie Hebdo massacre with the picture reprinted here.

wtorek, 6 stycznia 2015

New Year in Vienna

With ZK and his family we have spent 3 days in Vienna. If you are interested click the map below to see journey GPX track and photos.

We visited Schönbrunn Palace (a former imperial summer residence), Stephansdom, and Kunsthistorisches museum (where one can see Pieter Bruegel's famous paintings including: The Tower of Babel, The Fight Between Carnival and Lent, and The Hunters in the Snow).

We also visited Flak Towers which are enormous concrete bunkers constructed during 2nd world war. FLAK stands for Flug Abwehr Kanone (or Flugzeugabwehrkanone) and Flak Towers were a part (not particularly effective--mobile system is always better for obvious reason) of German air defence system intended to protect cities and residential areas from Allied air raids. Their construction was planned in September 1942 and Vienna was the third city after Berlin and Hamburg that got them.

The Flak Towers fulfilled two purposes (cf. Flak-Türme Towers, Vienna: Nazi concrete heritage at Vienna's heart): They held cannons and spotlights that should fight airplanes from the ground; and they were important bunkers with an autonomous electricity, air and water supply system. They were built in pairs, comprising of larger Gefechtsturm (Combat Tower) and a smaller Leitturm (Fire-control tower). The three pairs of Vienna can be found in the Augarten in the second district, the Arenberg Park in the third district and one each in the Esterhazypark in the sixth and the Stiftskaserne in the seventh.

We visited Augarten and Arenberg towers.

wtorek, 9 grudnia 2014

Afera madrycka: taka tam analiza wyjazdów posłów 7 kadencji

UWAGA: Ten tekst nie jest o polityce ale o [elementarnej] statystyce.

Media informowały, że posłowie PiS Adam Hofman, Mariusz A. Kamiński i Adam Rogacki wzięli na podróż do Madrytu na posiedzenie komisji Zgromadzenia Parlamentarnego Rady Europy po kilkanaście tysięcy złotych zaliczki, zgłaszając wyjazd samochodem; w rzeczywistości polecieli tanimi liniami lotniczymi. Ponieważ kontrola wydatków posłów jest iluzoryczna różnica pomiędzy kosztem podróży samochodem a samolotem [za dużo mniejsze pieniądze] miała stanowić dodatkowy przychód wyżej wymienionych. Według prokuratury, która wszczęła śledztwo, zachodzi podejrzenie popełnienia oszustwa.

Łapiąc wiatr w żagle [sprawa się upubliczniła tuż przed ostatnimi wyborami samorządowymi] koalicja rządząca w osobie Marszałka Sejmu RP Sikorskiego zarządziła audyt, którego efektem było udostępnienie m.in. dokumentu pn. Wyjazdy zagraniczne posłów VII kadencja (kopia jest tutaj).

Jak przystało na kraj, w którym od lat działa Ministerstwo cyfryzacji zestawienie jest w formacie PDF, zatem pierwszym ruchem była zamiana na coś przetwarzalnego. Wpisanie w google PDF+Excel+conversion skutkuje ogromną listą potencjalnych konwerterów. Bagatelizując skalę problemu spróbowałem dokonać konwersji narzędziami dostępnymi on-line, ale z marnym rezultatem (za duży dokument przykładowo; serwis za free jest tylko dla PDFów mniejszych niż 50 stron). W przypadku Convert PDF to EXCEL online & free coś tam skonwertował, nawet wyglądało toto na pierwszy rzut oka OK ale na drugi już nie: dokument niekompletny oraz nieprawidłowo zamienione niektóre liczby (przykładowo zamiast 837,50 zł w arkuszu jest 83750 -- 100 razy więcej!).

Ostatecznie skończyło się na ściągnięciu 30 dniowej wersji Adobe Acrobata Pro XI, który faktycznie sprawdził się w roli konwertera PDF→XLSX. Do konwersji wykorzystałem służbowego laptopa Elki wyposażonego w legalny Office 2010, na którym zainstalowałem ww. AA Pro XI. OOffice niby czyta XLSX, ale z koszmarnymi błędami, więc żeby dalej móc obrabiać arkusz w Linuksie wczytałem wynikowy XLSX do Excela 2010 po czym zapisałem go w (starszym) formacie XLS. Ten plik wyświetlił się w OO Calcu bez problemu.

Arkusz jest tak sformatowany, że 4 pierwsze komórki oraz są często wielowierszowe i scalone, zawierają bowiem liczbę porządkową, datę, miejsce i cel wyjazdu delegacji posłów. Po zamianie na plik CSV zawartość komórek scalonych pojawi się w pierwszym wierszu, a pozostałe będą puste. Prostym skryptem Perlowym mogę wypełnić puste komórki wg. algorytmu: jeżeli cztery pierwsze pola są puste, to skopiuj wartości ostatnich niepustych:


if ($tmp[0] eq '' && $tmp[1] eq '' && $tmp[2] eq '' && $tmp[3] eq '' ) { ... }

Pierwszy problem: wielowierszowe komórki z kolumn 1--4 nie zawsze są scalone. Czasem tekst jest podzielony na wiersze co psuje konwersję. Ręcznie scalam niescalone komórki (trochę to trwa). Przed scaleniem usuwam z kolumn 1--4 końce wiersza.

Drugi problem: część liczb nie jest liczbami z uwagi na użycie separatora tysięcy, który się zamienił w PDFie na odstęp (spację). Zatem zaznaczam kolumny zawierające różne pozycje kosztów po czym:

Edytuj→Znajdź i zamień
usuwam odstępy, tj. zamieniam spację na pusty napis
Format→Komórki
wybieram numer z dwoma miejscami po przecinku.

Po uporządkowaniu arkusza, zapisuję go w formacie CSV. Następnie prostym skryptem Perlowym zamieniam na taki plik CSV, w którym puste komórki są wypełniane zawartością z poprzednich wierszy. Kolumna Państwo - miasto jest kopiowana. Kopia jest zmieniana na jednoznaczne: Państwo, miasto (pierwszy-kraj, przecinek, pierwsze miasto z listy celów podróży -- żeby geokoderowi było łatwiej.)

Innym skryptem Perlowym dodaję do pliku CSV 3 kolumny, które zawierają:

  1. współrzędne celu podróży (w tym celu zamieniam adres Państwo, miasto na współrzędne geograficzne korzystając z geokodera Google);

  2. odległość w kilometrach pomiędzy punktem o współrzędnych 21.028075/52.225208 (W-wa, Wiejska 1) a celem podróży (obliczoną przy wykorzystaniu pakietu GIS::Distance);

  3. linię zdefiniowana w formacie KML o końcach 21.028075/52.225208--współrzędne-celu-podróży (do ewentualnego wykorzystania z Google Fusion Tables).


#!/usr/bin/perl
#
use Storable;
use Google::GeoCoder::Smart;
use GIS::Distance;

$geo = Google::GeoCoder::Smart->new();

my $gis = GIS::Distance->new();

my $GeoCodeCacheName = 'geocode.cache';
my $NewCoordinatesFetched=0; # global flag
my $SLEEP_TIME = 2 ;
my $coords_okr = "21.028075,52.225208"; # Warszawa = środek świata

my %GeoCodeCache = %{ retrieve("$GeoCodeCacheName") } if ( -f "$GeoCodeCacheName" ) ;
my ($wwa_lng, $wwa_lat) = split (",", $coords_okr);
my $linesNo = 0 ;
my $GCtotaluse = 1; # laczna liczba wywolan geocodera

while (<>) {
$linesNo++;
chomp(); $_ =~ s/[ \t]+;[ \t]+/;/g; ## usuń ew. niepotrzebne spacje

@line = split ";", $_; print STDERR "**$linesNo = $line[3] ... ";

# geokodowanie (uwaga na limit)
# Poprawki dla miejsc, których nie zna Google:
$line[3] =~ s/Erewań/Erywań/; ##
$line[3] =~ s/Sowayma/Madaba/; ## najbliższe miasto
$line[3] =~ s/Bołszowce/Iwano-Frankiwsk/; ## najbliższe miasto

my $coords = addr2coords( $line[3] );

($tmp_lat, $tmp_lng, $gcuse) = split " ", $coords;
if ($gcuse > 0) {$GCtotaluse++ ; }

$distance = $gis->distance($tmp_lat,$tmp_lng => $wwa_lat,$wwa_lng );
$distance_t = sprintf ("%.1f", $distance);

my $kml_line = "<LineString><coordinates>$tmp_lng,$tmp_lat $coords_okr</coordinates></LineString>";
print "$_;\"$coords\";$distance_t;\"$kml_line\"\n";
print STDERR "\n";

if ($GCtotaluse % 100 == 0 ) {# store every 100 geocoder calls
store(\%GeoCodeCache, "$GeoCodeCacheName");
print STDERR "\n... Cache stored. ***\n";
}
}

##
store(\%GeoCodeCache, "$GeoCodeCacheName");

## ## ## ####
sub addr2coords {
my $a = shift ;
my $r = shift || 'n';
my ($lat, $lng) ;
my $GCuse = 0;

##consult cache first
if (exists $GeoCodeCache{"$a"} ) {
print STDERR "Coordinates catched ... $a ";
($lat,$lng) = split (" ", $GeoCodeCache{"$a"} );
}
else {
print STDERR "Geocoding ... $a ";
my ($resultnum, $error, @results, $returncontent) = $geo->geocode("address" => "$a");
$GCuse = 1;
sleep $SLEEP_TIME; ## make short pause

$resultnum--;
$resultNo=$resultnum ;

if (resultNo > 0) { print STDERR "** Location $a occured more than once! **" }
if ($error eq 'OK') {
$NewCoordinatesFetched=1;
for $num(0 .. $resultnum) {
$lat = $results[$num]{geometry}{location}{lat};
$lng = $results[$num]{geometry}{location}{lng};
##print "*** LAT/LNG:$lat $lng ERROR: $error RES: $resultNo ***\n";
}

$GeoCodeCache{"$a"} = "$lat $lng"; ## store in cache

} else { print STDERR "** Location $a not found! due to $error **" }
}


if ($r eq 'r' ) { return "$lng,$lat,$GCuse"; } # w formacie KML
else { return "$lat $lng $GCuse"; }
}

Gotowy plik CSV zawierający zestawienie podróży jest dostępny tutaj.

Na podstawie zestawienia i z użyciem pakietu ggplot2 generują się takie oto śliczne wykresy.

Wszystkie podróże z zestawienie (N=1874; odpowiednio: koszt łączny, koszt transportu, długość w tys km):

Tylko podróże dla których koszt transportu był niezerowy (N=1423; odpowiednio: koszt łączny, koszt transportu, długość w tys km):

Poniższy skrypt R sumuje i drukuje wszystkie podróże każdego posła:


require(plyr)

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

# Dodaj kolumnę której wartości to konkatenacja: "Poseł|Klub"
d[,"PosKlub"] <- do.call(paste, c(d[c("Posel", "Klub")], sep = "|"));

# Usuń wszystko za wyjątkiem tego co potrzeba:
d <- d[ c("PosKlub", "Klacznie", "Ktransp", "Dist") ];

# Sumowanie po PosKlub
PSums <- as.data.frame ( ddply(d, .(PosKlub), numcolwise(sum)) );

# Z powrotem rozdziel kolumnę "Poseł|Klub" na dwie
PSums <- as.data.frame ( within(PSums, PosKlub <-data.frame( do.call('rbind',
strsplit(as.character(PosKlub), '|', fixed=TRUE)))) )

# Drukuj
PSums;

Z pliku .Rout kopiuję zestawienie łącznych wydatków posłów oraz łącznej pokonanej przez nich odległości:


PosKlub.X1 PosKlub.X2 KlacznieT KtranspT DistT
1 Adam Abramowicz PiS 4.02599 2.64595 1.3153
2 Adam Hofman PiS 119.55271 59.53315 26.1716
3 Adam Kępiński SLD 10.15754 7.93882 3.8069
4 Adam Kępiński TR 12.63098 8.02327 2.2107
...

Uwaga: kilkanaście nazwisk się powtarza ponieważ posłowie zmienili przynależność klubową w czasie trwania kadencji [Aby uwzględnić takich posłów sumowanie odbywało się po wartościach zmiennej zawierającej połączone napisy Poseł|Klub.]

Na podstawie takiego z kolei zestawienia i znowu z użyciem ggplot2 generują inne śliczne wykresy.

Uwaga: sumowane tylko podróże, dla których koszt transportu był niezerowy (N=1423; odpowiednio: koszt łączny, koszt transportu, długość w tys km):

Link do tabeli zawierającej zestawienie podróży w formacie Google Fusion Tables jest tutaj.

Dane + skrypty dostępne są także w: github.com/hrpunio/Data.

piątek, 5 września 2014

Trip to Georgia

I have just returned from a week-long trip to Georgia. We have visited Borjomi, Tbilisi, Kazbegi (Stepancminda) and Kutaisi (click the map to see journey track and photos).

On arriving to Kutaisi airport we went straight to the famous Borjomi resort where Russian Emperors once rested. We walked in the park tasting Borjomi mineral spring water, and swimming in hot water pool. From Borjomi we visited cave-city and monastery ensemble Vardzia where there was other hot water pool (with even hotter water). After 2 days in Borjomi we went to Tbilisi where we stayed 1 day (walking in old town). Next morning we drove to Caucasus mountains along Georgian military road via ancient Capital of Georgia -- Mtskheta (unfortunately we did not stop there). We stayed 2 days in Kazbegi where we hiked to Gergeti Trinity Church at 2170m and attended rugby union game Kazbegi vs Tbilisi Crusaiders (among other things:-). Finally we returned to Kutaisi where we visited Gelati and Motsameta Monastyrs as well as Sataplia caves...

We stayed in Leo's Homestay/Guesthouse in Borjomi, Why Not? Legend Hostel in Tbilisi and Hostel Kutaisi by Kote in Kutaisi. We recommend all of them.

The guesthouse we stayed in Kazbegi is not recommended so we do not mention it:-(

More details later...

środa, 23 lipca 2014

Batch upload to Picasa

The problem: upload photos to Picasa (trivial); 2) scale them if neccessary before upload; 3) if photos contains some EXIF tags (geotags in particular) copy these tags to Picasa as well.

To achieve the above I use: googleCL (upload), convert (from ImageMagick bundle for scaling) exiftool (for metadata extraction/manipulation).

Using convert the script below (jpgresize.sh) scale picture to 2048 pixels along longest side:


#!/bin/bash
# Scale pictures to 2048 pixels along longest side for upload to Picasa
# Photos below 2048 x 2048 pixels do not count towards storage limit
# (cf. https://support.google.com/picasa/answer/6558?hl=en )
#
PICASA_FREE_LIMIT=2048

while test $# -gt 0; do
case "$1" in
-o) shift; OUT_FILE="$1";;
-o*) OUT_FILE="`echo :$1 | sed 's/^:-o//'`";;
*) FILE="$1";;
esac
shift
done

if [ -z "$OUT_FILE" ] ; then
my_pic="${FILE%.*}_s.${FILE#*.}"
else
my_pic="$OUT_FILE";
fi

if [ -f "$FILE" ] ; then

echo "** converting $FILE to $my_pic ***"

SIZE="2048x"

my_pic_width=`exiftool -ImageWidth "$FILE" | awk '{print $NF}'`
my_pic_height=`exiftool -ImageHeight "$FILE" | awk '{print $NF}'`

if [[ ( -z "$my_pic_width" ) || ( -z "$my_pic_height" ) ]] ; then
echo "*** $FILE has 0 width and/or height ***"; exit ;
fi

## http://www.imagemagick.org/Usage/resize/#resize
if [[ ( "$my_pic_width" -gt "$PICASA_FREE_LIMIT" ) || \
( "$my_pic_height" -gt "$PICASA_FREE_LIMIT" ) ]] ; then
if [ "$my_pic_width" -gt "$my_pic_height" ] ; then
SIZE="${PICASA_FREE_LIMIT}x>"
echo "*** $FILE width: $my_pic_width ; converting to $SIZE"
convert "$FILE" -geometry $SIZE "$my_pic"
else
SIZE="x$PICASA_FREE_LIMIT>"
echo "*** $FILE height: $my_pic_height ; converting to $SIZE"
convert "$FILE" -geometry $SIZE "$my_pic"
fi
else
## File is too small copy the original:
echo "*** $FILE has $my_pic_width in width; COPYING"
cp "$FILE" "$my_pic"
fi
else
echo "*** FILE $FILE not found! ***"
fi

Upload one picture to picasa with 1photo2picasa.sh


#!/bin/bash
#
# Upload photo to Picasa with googleCL
# It is assumed the photo contains UserComment GPSLatitude GPSLongitude GPSAltitude
# Exif tags which are copied to Picasa (see below for more details)
#
# Default album title:
ALBUMTITLE="???"

echo "$0 -a AlbumTitle FILE-2-UPLOAD"

while test $# -gt 0; do
case "$1" in
-a) shift; ALBUMTITLE="$1";;
-a*) ALBUMTITLE="`echo :$1 | sed 's/^:-a//'`";;
*) FILE="$1";;
esac
shift
done

AUTHOR=`exiftool -S -Artist $FILE`

if [ -z "$AUTHOR" ] ; then
# It there is no Artist tag it is assumed photo was not tagged properly
echo "*** ERROR: $FILE lacks Artist EXIF tag"
exit;
else
## Some tags are edited:
TAGS=`exiftool -S -UserComment $FILE | awk '{ $1=""; for (i=1;i<=NF;i++) { if ($i ~ /http/) { $i=""}}; \
gsub (/, +/, ",", $0); gsub (/ +,/, ",", $0); gsub (/^ +| +$/, "", $0); print $0}'`
GPSLat=`exiftool -S -c '%+.6f' -GPSLatitude $FILE | awk '{ print $2}'`
GPSLon=`exiftool -S -c '%+.6f' -GPSLongitude $FILE | awk '{ print $2}'`
GPSAlt=`exiftool -GPSAltitude $FILE -S -c "%.1f" | awk '{ if ($0 ~ /Below/) { print -$2} else {print $2}}'`

PICASA_TAGS=""
## Concatenate all tags
if [ -n "$TAGS" ] ; then PICASA_TAGS="$TAGS"; fi
if [ -n "$GPSLat" ] ; then PICASA_TAGS="$PICASA_TAGS,geo:lat=$GPSLat"; fi
if [ -n "$GPSLon" ] ; then PICASA_TAGS="$PICASA_TAGS,geo:lon=$GPSLon"; fi
if [ -n "$GPSAlt" ] ; then PICASA_TAGS="$PICASA_TAGS,geo:alt=$GPSAlt"; fi

# Upload to picasa:
google picasa post --title "$ALBUMTITLE" --src="$FILE" --photo="$FILE" --tags="$PICASA_TAGS"
fi

Finally simple bash script upload2picassa.sh uses jpgresize.sh and 1photo2picasa.sh to upload all .jpg files from the current directory to picasa:


#!/bin/bash
# Upload all .jpg files (scaled tp 2048) to picasa
#
echo "Uploading all .jpg files to album: $albumtitle"

albumtitle=$1

if [ -z "$albumtitle" ] ; then
echo "Podaj ID albumu!"; exit 1
fi

for file in *.jpg; do

echo "Uploading $file to $albumtitle album..."

outfile="${file%.*}_s.${file#*.}"

jpgresize.sh -p -o $outfile $file && 1photo2picasa.sh -a $albumtitle $outfile
done

wtorek, 22 lipca 2014

Flickr zmienił API

Wycieczka do Swornychgaci spowodowała m.in. konieczność dopasowania moich starych skryptów Perla służących do obsługi Flickra.

Flickr zmienił bowiem niedawno API przechodząc na SSL. Zapewne nowa wersja modułu Flickr-API tą zmianę uwzględnia, ale można też rozwiązać sprawę dodając stosowny parametr do starych skryptów. Konkretnie poniższy wiersz:


my $api = new Flickr::API({'key' => $api_key, 'secret' => $shared_secret, });

należy uzupełnić o parametr rest_uri, tj:


my $api = new Flickr::API({'key' => $api_key, 'secret' => $shared_secret,
'rest_uri' => 'https://api.flickr.com/services/rest/' });

Podobnie niewielkich modyfikacji wymaga skrypt służący do wysyłania zdjęć (moduł Flickr-Upload):


my $ua = Flickr::Upload->new( {'key' => $api_key, 'secret' => $shared_secret,
'uri' => 'https://up.flickr.com/services/upload/' } );

W tzw. międzyczasie zmieniła się też nieco metoda flickr.photos.geo.setLocation:


#if ( $response->{success} ) { ## przestało działać
unless ( $response->{error_code} > 0 ) {

W dokumentacji jest napisane: This method has no specific response -- It returns an empty success response if it completes without error.. No to faktycznie jak jest empty to if (EMPTY) { zwraca fałsz i warunek jest źle interpertowany. Poza tą jedną poprawką wszystko inne działa.

Wycieczka do Swornychgaci

We piątek (18.07.2014) przepłynęliśmy z rodziną kolegi ZK rzeką Chociną, konkretnie od Chocińskiego Młyna do jeziora Karsińskiego (ca 12 km na GPSie). Spływ zaczęliśmy w Chocińskim Młynie około 14:30 a do Swornychgaci dotarliśmy po 18:00.

Rzeczka jest płytka i wąska, ale nie ma w niej żadnych przeszkód. Spływ odbył się zatem bezproblemowo. Chcieliśmy także popłynąć kajakami w niedzielę, niestety, wszystkie okoliczne wypożyczalnie kajaków miały cały swój tabor zarezerwowany.

Miłym rozczarowaniem jest sieć pierwszorzędnych dróg rowerowych w okolicy Chojnic, o istnieniu których nie miałem świadomości. Drogi rowerowe są wytyczone obok drogi dla samochodów, wydają się dobrze oznakowane i mają utwardzoną nawierzchnię (niekoniecznie asfalt czy płytki/kostki). Do roweru szosowego nie nadają się na 100%, ale każdy inny będzie OK, a i na szosowym da się jechać. Na szybko jakieś informacje na temat tych dróg znalazłem tutaj (niekoniecznie musi to być najlepsze źródło).

Wracając wpadliśmy obejrzeć akwedukt w Fojutowie. Rozczarowująca atrakcja. Do tego tłum ludzi--nie wiem czemu akurat to miejsce jest aż tak popularne...

Ślad całej wycieczki (ze zdjęciami) jest też tutaj.

poniedziałek, 21 lipca 2014

Letter from an Idiot

Not very long ago, there was a lot of LGBT propaganda before Sochi Olympics Games related to alleged Putin's war with LGBT Russians. Opinion leader Stephen Fry's open letter to PM Cameron/IOC was a good example of hysteria created then.

IMHO the letter was extremely stupid (as stupid as its creator), namely Putin was compared to Hitler and LGBT Russians to Jews in the 3rd Reich (He is making scapegoats of gay people, just as Hitler did Jews).

Unfortunately Putin started a real war, not a war with some scapegoats.... And of course comparing 6 millions murdered Jews with `suffering gays' is pure and simple grave robbery (taniec na trumnach in Polish).

Fry's letter is here