Gistacular: Ein mobiles Zuhause für Gist

Was für eine prächtige Ergänzung das kleine Gistacular zu iOctocat ist. Zwar kann ich Gists auch dort ansehen, aber nicht bearbeiten. Gistacular schließt diese Lücke auf einfache Weise.

Die App ist ein stromlinienförmiger Client für Gists. Alles ist übersichtlich angeordnet. Ich kann Favoriten verwalten, Skripte anderer Leute durchforsten, neben den eigenen Skripten natürlich. Der Texteditor ist spartanisch, aber ausreichend. Aber Gistacular zeigt in der Vorschau auch Syntax-Highlighting.

Ich sehe langsam, dass ich meine Desktoprechner nur noch für wirklich umfassende Schreibarbeiten oder eben Spiele brauchen werde. Alles andere kann ich immer besser auch von mobilen Geräten erledigen.

Übrigens, der Quellcode von Gistacular ist freundlicherweise auch auf Github.

Bilder: iTunes

Drafts-Rezepte VII: Postleitzahlen mit Zippopotamus II

Der zweite Teil zu Postleitzahlen mit Zippopotamus geht in die entgegengesetzte Richtung. Statt nun also eine Postleitzahl zu ermitteln, geht es nun um die Städte oder Stadtteile hinter eine Postleitzahl.

Das Script ist wieder genauso einfach wie das erste. In Drafts muss eine neue Notiz nur die folgende Syntax einhalten:

[PLZ],[LÄNDERKÜRZEL]

Beispielsweise würde die folgende Eingabe der berühmten Postleitzahl eine Markdown-Liste in Drafts öffnen.

90210 , us

Auch hier kommt ein kleiner Haken ins Spiel, auch wenn er nicht ganz so lästig ist. Denn die API von Zippopotamus erlaubt es derzeit nicht, das Land nicht anzugeben. Unter Umständen müssen wir also mehr Infos angeben, als wir haben. Das Python-Script sieht derzeit so aus:

# -*- coding: utf-8 -*-
from console import alert
from json import loads
from sys import argv, exit
from urllib import urlopen, quote
import webbrowser

def error_dialog(title, message):
    '''
    a diaolog box for error messages.
    '''
    try:
        alert(title, message)
    except KeyboardInterrupt:
        pass
    webbrowser.open('drafts://')
    exit(message)

def handle_data(data):
    '''
    process json response from zippopotamus.
    will return a markdown list of items.
    '''
    city_json = loads(data)
    output = ''
    for item in city_json['places']:
        output += '- Ort: {place}, Region: {state}\n'.format(place=item['place name'], state=item['state'])
    return output

def get_by_postalcode(data):
    '''
    get all possible cities for a postal code in
    the given country.
    '''
    api_url_base = 'http://api.zippopotam.us/{country}/{postcode}'
    try:
        postcode_, country_= [item.strip() for item in data.split(',')]
    except Exception as err:
        error_dialog(str(err.__class__), err.message)

    try:
        response = urlopen(api_url_base.format(country=country_, postcode=postcode_))
    except IOError:
        error_dialog('Connection Error', 'Unable to perform request.')
    if response.getcode() == 200:
        postcode_data = handle_data(response.read())
        webbrowser.open('drafts://x-callback-url/create?text={0}'.format(quote(postcode_data)))
    else:
        error_dialog('Error', 'Status code: {0} - Message: {1}'.format(response.getcode(), response.read()))

if __name__ == '__main__':
    get_by_postalcode(argv[1])

Gist

Die dazugehörige Action für Drafts ist:

pythonista://city-by-postalcode?action=run&argv=[[draft]]

Import-Link

Drafts-Rezepte VI: Postleitzahlen mit Zippopotamus I

Den kleinen Gag kann ich mir nicht verkneifen. Ich mache zu Zippopotamus, einem guten, kleinen Dienst für Postleitzahlen in einer Vielzahl von Ländern, zwei Teile. Damit artet die Kleinteiligkeit aus wie der überbordende Song-Kosmos von Coheed & Cambria.

Das Script ist wieder sehr einfach. In Drafts muss eine neue Notiz nur die folgende Syntax einhalten:

[STADT], [REGIONSKÜRZEL], [LÄNDERKÜRZEL]

Beispielsweise würde die folgende Eingabe die berühmte Postleitzahlen für die Stadt als Markdown-Liste in Drafts öffenen.

beverly hills, ca, us

Leider kommt diese Sache nicht ohne einen kleinen Haken aus. Denn die API von Zippopotamus erlaubt es derzeit nicht, die Region und das Land nicht anzugeben. Unter Umständen müssen wir also mehr Infos angeben, als wir haben. Ich bin dabei, mir dafür eine Lösung zu überlegen. Das Python-Script sieht derzeit so aus:

# -*- coding: utf-8 -*-
from console import alert
from json import loads
from sys import argv, exit
from urllib import urlopen, quote
import webbrowser

def error_dialog(title, message):
    '''
    a diaolog box for error messages.
    '''
    try:
        alert(title, message)
    except KeyboardInterrupt:
        pass
    webbrowser.open('drafts://')
    exit(message)

def handle_data(data):
    '''
    process json response from zippopotamus.
    will return a markdown list of items.
    '''
    city_json = loads(data)
    output = ''
    for item in city_json['places']:
        output += '- City: {place}, Post code: {postcode}\n'.format(place=item['place name'], postcode=item['post code'])
    return output

def get_by_city(data):
    '''
    get all possible post codes for a city in
    the given country.
    '''
    api_url_base = 'http://api.zippopotam.us/{country}/{state}/{city}'
    try:
        city_, state_, country_= [item.strip() for item in data.split(',')]
    except Exception as err:
        error_dialog(str(err.__class__), err.message)

    try:
        response = urlopen(api_url_base.format(country=country_, state=state_, city=city_))
    except IOError:
        error_dialog('Connection Error', 'Unable to perform request.')
    if response.getcode() == 200:
        city_data = handle_data(response.read())
        webbrowser.open('drafts://x-callback-url/create?text={0}'.format(quote(city_data)))
    else:
        error_dialog('Error', 'Status code: {0} - Message: {1}'.format(response.getcode(), response.read()))

if __name__ == '__main__':
    get_by_city(argv[1])

Gist

Die dazugehörige Action für Drafts ist hier:

pythonista://postalcode-by-city?action=run&argv=[[draft]]

Import-Link

Wilfred: Sittenstrolch

Wer in der Reihe der fantastisch erfolgreichen Verfilmungen von Tolkiens Herr der Ringe Hauptdarsteller war, sollte keine weltlichen Sorgen kennen. Ein gutes Management vorausgesetzt, sollten die Verträge einer effektiven Frührente für Bestbetuchte gleichkommen. Über all diese Voraussetzungen dürfte Elijah Wood verfügen, so schließt sich die eine Frage an: Was nun?

Wood wirkt nicht wie der Typ Schauspieler, der sich der Dekadenz hingibt. Über einen halben Planeten zwischen uns und die absolute persönliche Unbekanntheit setze ich mich hinweg, indem ich von Wood annehme, dass er sich nur den Luxus gönnt, eben noch die Projekte anzunehmen, die ihm den größten Nutzen versprechen. Da müsste er doch eigentlich in Erklärungsnot geraten, was ihn geritten hat, in einer Serie mitzuspielen, in der nur der von ihm gespielte Ryan nach einem erfolglosen Selbstmordversuch durch Medikamentenüberdosis den Hund seiner Nachbarin als Mittdreißiger im flauschigen Hundekostüm sieht?

Worum es in Wilfred geht, ist schwer in Worte zu fassen. Es ist, wie es oben beschrieben wurde. Ein depressiver Mann hat einen imaginären Freund in dem Hund seiner Nachbarin gefunden, für die er auch noch, fast selbstverständlich, Gefühle hegt. Ryan und Wilfred stolpern von einer abstrusen Schweiner in die nächste. Wilfred ist dabei nichts peinlich. Wieso auch, er ist ein Hund. Ryan und auch sein Gewissen aber müssen desöfteren beruhigt werden. Da trifft sich hervorragend, dass beide leidenschaftlich gern kiffen. Das soll ja ausgleichend wirken.

Die Serie ist eines nicht, auch wenn es sich so anhört: albern. Sie zu beschreiben läuft, wie gesagt, Gefahr, sie ins Lächerliche zu ziehen. Im besten Falle ist sie ein rigoroser Verstoß gegen den guten Geschmack. Meist jedoch entpuppen sich die Handlungsstränge als subversive Dramedy. Unter dem Kostüm des Hundes steckt ein Es; eine ungebremste, triebhafte Erscheinung, die Ryans Leben zu gleichen Teilen zu heilen wie zu ruinieren in der Lage ist. Der imaginierte Hund ist eine entgrenzte, hemmungslose Instanz irgendwo zwischen Ryans Fremd- und Selbstwahrnehmung.

In Wilfred bricht eine besondere Form anarchischen Humors hervor. Die Perspektive des Hundes erlaubt es, die menschlichen Normen zu brechen, ohne dabei plump in Gossenhumor auszupacken. Nicht dass die Gosse nicht Thema wäre, aber erfreulicherweise entsteht der Humor daraus, dass Ekel, Abscheu und Grenzverstöße mit der manischen Freude eine Hundes daherkommt, der sich an unsere Regeln nicht halten muss. Meist entsteht der Humor auch nur verbal, ist damit eleganter als mit dem Holzhammer vorgetragener Klamauk. Ein widerwärtiger Spaß.

Timely Alarm Clock: Form auf Höhe der Funktion

Muss ich über Timely noch wirklich viele Worte verlieren, muss ich? Eine halbe Woche mindestens bin ich zu spät dran, also eine Ewigkeit, in der Lob kübelweise über diesen Wecker für Android ausgeschüttet wurde. Da rechtfertigt nur ein Verriss oder eine kleine, pointierte Kritik, um jetzt noch mit ein paar Sätzen über die App rauszukommen. Weit gefehlt, ich kann nur in den Chor einstimmen.

Vor einiger Zeit schrieb ich noch von Rise auf iOS, dem Timely in vielen Punkten ähnlich ist, in den meisten sogar überlegen. Optisch ist Timely um Welten ansehnlicher als jede durchschnittliche Android-App. Nicht nur das, Timely ist schön. Flaches Design, ja wir spüren den Zeitgeist, mit subtilen Effekten. Der Nutzbarkeit steht das nie im Weg. Timely ist ein Muster an intuitiven Bedienelementen, ich arbeite wie im Traum mit dem Wecker, der Uhr, Timer und Stoppuhr. Ich schwebe durch die App, keine Übertreibung.

Kostenlos ist Timely in seiner grundlegenden Form, weitere Themes, Weckersynchronisation über mehrere Geräte hinweg und vor allem einige fantastische Wecktöne lassen sich einzeln oder als Paket hinzu kaufen. Nicht aber, ohne dass die meisten Zusatzinhalte vorher in einer Testphase für einige Tage kostenlos zur Verfügung zu stehen. So fair ist Timely, alle Kosten sind transparent, ich wünsche mir, dass es sich auszahlt. Und selbst wenn ich auf der kostenlosen Schiene hätte bleiben wollen, ich hätte einen fantastischen Wecker gehabt. Timely ist ohne böse Überraschungen eine grandiose App, aber auch ein Blick in eine Zukunft fernab der biederen Nacktmulche von Software, die ich mir schweren Herzens auf den Android schob. Android kann schön sein, kombiniert mit solch durchdachter Funktionalität sogar ästhetisch.

Der Horror: trakt.tv und Android

Ich wollte ja nur eine App, die mir erlaubt, Serien auf trakt.tv auch unter Android zu verwalten. Letzte Woche schrieb ich über 60Hz, das auf iOS läuft, aber leider derzeit auf der Performance-Seite etwas zu wünschen übrig lässt. Das war aber nichts gegen meine Versuche unter Android, wie sich jetzt rückblickend herausstellte. Dabei halte ich meine Ansprüche gar nicht für allzu hoch. Im Grunde möchte ich doch nur meinen Account bei trakt.tv nutzen, dort neue Serien oder Filme verwalten und diese gegebenenfalls als gesehen zu markieren und bewerten.

In der ersten Runde fielen dann gleich schon so Apps wie Damnent, moviis, anpMovies, Movie Trakt und TV Trakt  raus. Ich verstehe zwar, warum sie eine Unterscheidung zwischen Film und Serien machen wollen, für mich ist das allerdings nicht sinnvoll, selbst wenn ich überwiegend Serien schaue. Ebenso vielversprechend wirkte auch Twee, doch auch das blendete Filme einfach aus. Die Liste der möglichen Kandidaten ließ also schon an der ersten Hürde eine Menge Apps aus dem Rennen fallen. Dann geht es eben mit den verbliebenen Kandidaten weiter.

Ich kann aber gleich auch noch bei Twee bleiben, denn diese eigentlich ganz ordentlich gemachte App wäre auch an der zweiten Aufgabe gescheitert. Beim besten Willen will mir nicht in den Kopf, warum eine App einen dritten Webdienst für die Daten und Synchronisierung nutzt, der recht gut verbreitet ist, und erlaubt dann nicht, einen bestehenden Account zu nutzen. Ich weiß nicht, was Twee da macht, ob sie irgendwie anhand der Gerätenummern einfach neue Accounts bei trakt.tv anlegen. Wie auch immer. Was nutzt es, dass ich mir bei trakt.tv eine Bibliothek aufgebaut habe, die ich nun nicht nutzen kann? Und Twee ist nicht allein damit, auch das anscheinend sehr beliebte SeriesGuide Probleme, meine Anmeldung durchzuziehen. Ich gebe meine Anmeldedaten von trakt.tv ein, es scheitert jedes Mal. Diese Krankheit scheint TV Shows Favs nicht zu haben. Ich war mal großzügig und ließ es die erste Runde überstehen, obwohl es nur Serien verwaltet. Es brauchte dann aber eine Weile, bis ich merkte, dass die Anmeldung irgendwie meine Daten nicht akzeptierte, sondern eigene Accounts verlangte. Die größte Enttäuschung zu diesem Zeitpunkt war Cliffhanger. Zwar musste ich mich da auch nur mit Serien begnügen, aber in vielen anderen Punkten sah es toll aus. Doch auch hier ist die Anmeldung bei trakt.tv zwar versprochen, aber noch lange nicht umgesetzt. So schlossen McTrakt, das derzeit noch eine Beta ist, und Chakt, das sogar alpha ist, die zweite Runde ab. Deren Entwicklungsstatus hilft mir eben auch nicht, wenn meine Accountdaten ständig nicht verifiziert wurden.

Mehr als die Hälfte der Kandidaten war nun schon nicht mehr dabei. Nur mit einiger Großzügigkeit blieben zu diesem Zeitpunkt noch Apps, die eventuell früher hätten ausscheiden müssen. Aber ich war gnädig, ich konnte ja nicht gleich alle scheitern lassen. TraktApp war schnell und gut, zickte auch nicht bei meinem Account herum. Was für eine Erleichterung. Lediglich das Bewerten von Serien ist nicht möglich, wie ich es gerne hätte, und sehr ansehnlich ist die App wirklich nicht. Aber es hat ja einen Grund, warum ich die Optik nicht zu einem Kriterium gemacht habe, wir reden hier schließlich von Android-Apps. Bei Traktoid bluteten meine Augen nicht mehr, die Synchronisierung der Daten lief eigentlich recht ordentlich, aber es verwaltet nur Serien. Wenn ich also hart bliebe, müsste die App auch aus dem Rennen sein, genauso wie Traktato, das ich schon von iOS kenne. Traktato hat es aber geschafft, weil es die Serien in meinem trakt.tv-Account immerhin in einer vergleichsweise schicken Oberfläche verwaltet und dabei nur die Bewertungsmöglichkeit vermissen lässt. Ansonsten läuft schnell und zuverlässig. Als letzte in der langen Reihe blieb dann noch Voodoo TVDB. Die App ist sehr ansehnlich, lässt aber schon im Namen erkennen, eigentlich für nur für Serien gedacht zu sein. Die App wirkte so gut, ich hätte beinahe übersehen, dass eine Accountanmeldung bei trakt.tv auch erst in Zukunft möglich sein sollte. Dann auch noch nur im gewünschten Umfang in der PRO-Version.

Das war es. Das war alles an Apps. Es machte sich bei mir mehr als nur Ernüchterung breit. Denn damit hatte ich nicht gerechnet. Es war sogar eine recht herbe Enttäuschung, denn es gibt einige Apps, die viel versprechen, aber unterm Strich nicht alles halten. Nach dem jetzigen Stand nutze ich, allerdings auch nur recht widerwillig, Traktato. Aber eigentlich ist es ein karges Ergebnis, dass von mir als Grundfunktionen empfundene Optionen nicht verfügbar sind. Im Grunde besteht aber keine der Apps gegen die trakt.tv-Seite im Browser. Das ist zwar auch eine Qual, bietet aber alles, was ich will.

 

Thunderspace: Im Auge des Sturms

Mit einer Beschreibung wie „stereoscopic 3D audio“ weiß ich herzlich wenig anzufangen. Höre ich aber über die Kopfhörer meines Telefons einem Gewitter in aller Räumlichkeit zu, verstehe ich, was gemeint ist. Das Donnern rollt plastisch durch meinen Kopf, der beständige Nieselregen prasselt so lebendig auf meine Ohren ein, ich glaube, jeden einzelnen Tropfen zu hören.

In gewissen Sinne ist Thunderspace das Muster für eine richtig gute App. Nur ein einziger, einzelner Zweck wird schnörkellos umgesetzt. Thunderspace entspannt mit beeindruckenden Tonaufnahmen von Unwettern. Zugegeben, dafür muss man der Typ sein, sich in Hintergrundrauschen zu verlieren. Ich bin es. Deshalb bin ich so begeistert von Thunderspace, wo Stürme eine sichere und beruhigende Klangkulisse sind.

Drumherum gibt es nicht viel Ablenkung, das finde ich hervorragend. Zwei Klangbetten sind kostenlos enthalten*, sechs weitere sind über IAP zu haben. Das ist alles in allem fair. Thunderspace kommt im zugegeben schicken iOS7-Design daher, auch wenn die Gradients jetzt schon beliebig zu werden drohen. Aber egal, es geht ums Gewitter in den Ohren, das Ruhe im Kopf machen soll. Die Illusion vom Unwetter soll durch über die Gerätleuchte simulierte Blitze verstärkt werden, aber das brauche ich nicht wirklich. Nützlicher ist der Sleep-Timer. In meinen Ohren ist das eine der besten Entspannungsmöglichkeiten, die der App-Store bislang zu bieten hat.

* Update 21.08.2013: Da war ich etwas verwirrt. Thunderspace ist prinzipiell im unteren Preissegment angesiedelt, war nur vorübergehend kostenlos. Ich halte die Freemium-Variante prinzipiell für besser, aber selbst für die kleine Einstiegshürde bieten die zwei Klangbetten ordentlich Entspannung.

10000000: Schlachte-drei-Monster-oder-mehr

Warum heißt 10000000 so? Simpel. Der namenlose Held des Spiels benötigt zehn Millionen Punkte. Sobald er diese in einem Retroverlies erspielt hat, kann er aus seinem Gefängnis fliehen. Hm, das reicht schon als Motivation, also her mit den Monstern.

Für manchen alteingesessenen Spieler ist die Entwicklung der mobilen Spiele ein retrograder Prozess. Fossilien der Spiele leben neu auf, werden auch noch für ihre spartanische Aufmachung gelobt. Ein Graus, für AAA-Spielesnobs. Denn es gibt so kleine Schätze. 10000000 ist so ein Spiel, das sich zwei altbekannte Muster schnappt und sie hybridisiert.

Das recht simple Konzept der Match-3-Spiele wird mit der Mechanik von Rollenspielen kombiniert. Der Held wird nich direkt gesteuert, er läuft zielstrebig durch die Gewölbe. Als Spieler müssen wir dafür sorgen, dass ihm nicht die Kraft ausgeht. Dafür hält das Match-3 her, auf dem Spielfeld sind Zeichen für Ressourcen, Angriffstechniken und das Öffnen von Schlössern verteilt. Je nach Aufgabe, der sich der Held gegenüber sieht, müssen mindestens drei der entsprechenden Felder verbunden werden, damit deren Kraft freigesetzt wird. Je länger der Held überlebt, desto näher kommt er dem Punktziel. Zwischen den einzelnen Läufen im Dungeon kann der Held die Ressourcen auch noch in kleinen Shops auf den Kopf hauen. Die Verbesserungen lassen das Ziel der zehn Millionen Punkte dann nicht mehr ganz so utopisch klingen, wie es anfangs erscheint.

Als Hybrid macht 10000000 vieles richtig. Ein gut umgesetzter Rollenspiel- und Leveling-Anteil macht jedes Spiel attraktiver; und hier ist es sehr gut umgesetzt, wenn der Fortschritt auch ein wenig zu linear verläuft. Bis das Ziel des erreicht ist, vergehen so ein paar Stunden. Überwiegend auch wie im Flug, denn nur selten kommt Langeweile auf. Dennoch bezweifle ich, dass es ein sehr langlebiges Spiel ist, denn dafür ist es langfristig zu monoton. Aber sehr gut für das, was es sein will.

Rise Alarm Clock – Aufstehen

Aufgepasst, Freunde des gepflegten Minimalismus, heute ist Rise Alarm Clock kostenlos. Eigentlich ist sie überflüssig, iOS bringt doch einen Wecker schon mit. Aber wie so oft, die native App bringt nur die allernötigsten Funktionen mit.

Bei Rise ist jedes Fett sorgsam abgeschnitten, die App ist vorbildlich designt. Die Weckzeit kann per Touch einfach eingestellt werden, da ist es nur bedauerlich, dass Rise immer bloß einen Wecker erlaubt. Komfortabler ist da schon, dass die Klingeltöne erlesen sind und auch noch aus der eigenen Bibliothek ergänzt werden können. Ein weiteres Plus, ich weiß beim besten Willen nicht, warum das so oft unter den Tisch fällt, ist der skalierbare Snooze-Button. Aber am besten einfach mal ausprobieren, schadet ja nichts.

Drafts-Rezepte V: Wetterdaten mit OpenWeatherMap

Ich habe mir wieder ein kleines Skript (current_weather.py) gebastelt, mit dem ich für einen beliebigen Ort die aktuelle Temperatur und Luftfeuchtigkeit erhalte. Als Datenquelle dient die API von OpenWeatherMap, abgerufen wird es wieder über Pythonista. Das Skript sieht folgendermaßen aus:

# -*- coding: utf-8 -*-
import clipboard
from console import alert
from json import loads
from sys import argv, exit
from urllib import urlopen, quote
import webbrowser

def error_dialog(title, message):
  '''A diaolog box for error messages.'''
	try:
		alert(title, message)
	except KeyboardInterrupt:
		pass
	webbrowser.open('drafts://')
	exit(message)

def filter_data(data):
	'''create output string from response'''
	weather = loads(data)
	temperature = weather['main']['temp']
	humidity = weather['main']['humidity']
	output = 'Temperatur: {0} Celsius\nLuftfeuchtigkeit: {1}%'.format(temperature, humidity)
	return output

def get_current_weather_in(data):
	'''get current weather data'''
	api_url_base = 'http://api.openweathermap.org/data/2.5/weather?q={0}&units=metric&lang=de'
	try:
		response = urlopen(api_url_base.format(data))
	except IOError:
		error_dialog('Connection Error', 'Unable to perform request.')
	if response.getcode() == 200:
		weather_data = filter_data(response.read())
		webbrowser.open('drafts://x-callback-url/create?text={0}'.format(quote(weather_data)))
	else:
		error_dialog('Error', 'Status code: {0} - Message: {1}'.format(response.getcode(), response.read()))

if __name__ == '__main__':
	get_current_weather_in(argv[1])

Gist

Das Skript kann dann über die Drafts-Action ausgeführt werden:

pythonista://current_weather?action=run&argv=[[draft]]

Import-Link

Im Grunde war das auch schon alles. In Drafts muss dann in einer neuen Notiz nur der Name der Stadt eingegeben werden. Gegebenenfalls sollte sicherheitshalber noch das Land hinzugefügt werden. So würde Hamburg, de mir die aktuelle Temperatur und Luftfeuchtigkeit für Hamburg geben.