Modmic
An der Uni habe ich Zugang zu einem 3D-Drucker. Herausgekommen ist das hier:
Es ist ein Halter für ein Ansteck-Mikrofon, der seitlich an den Kopfhörer geklebt wird. Hintergrund ist, dass ich der Empfehlung des hifi-forums gefolgt bin und statt eines Headsets einen Kopfhörer samt Ansteckmikrofon gekauft habe. Im Grunde war das auch eine gute Idee, besonders der Kopfhörer ist wirklich besser als deutlich teurere Headsets. Aber das Anstecken des Mikrofons hat mich irgendwann genervt, vor allem nachdem der Plastikhalter abgebrochen ist.
Der Prototyp ist zusammengeklebt. Natürlich habe ich zuerst wesentlich kompliziertere Lösungen mit Steckverbindungen und Gelenken gebaut, so richtig haben die aber bisher noch nicht funktioniert. Wie einfach die Lösung jetzt ist sieht man vielleicht besser am CAD-Modell:
Wings3D hat sich für mich als absoluten CAD-Anfänger als gutes Werkzeug erwiesen, um unter Ubuntu das Modell zu erstellen. Blender war mir von Anfang an zu kompliziert und zu störrisch für diese eigentlich einfache Aufgabe. Bei Google Sketchup wurde mir nicht klar, ob die kostenlose Version des Programms alles nötige kann. Freecads Oberfläche blieb für mich völlig undurchschaubar.
Mit Wings3D dagegen kamen recht schnell erste Modelle zustande. Die Basisblöcke können per Rechtsklick eingefügt und einfach durch den Raum geschoben werden. Das Manipulieren der Linien, Flächen und Punkte wurde mir sofort klar. Außerdem das einzige Programm, dessen Kamerasteuerung intuitiv funktioniert. Böse Stolperfalle jedoch ist die "Hole"-Funktion zum Einfügen von Löchern in Objekte: Die blendet Vektoren nur aus, aber entfernt sie nicht, was bei späterer Manipulation des Objekts unspeicherbare Modelle produziert. Dass man sie nicht wirklich nutzen soll findet man im Forum, dass stattdessen die "Intrude"- und "Inset"-Funktionen, angewandt gleichzeitig auf die gegenüberliegenden gleichgroßen Seiten eines Modells, die Aufgabe erledigen, war schon schwerer herauszufinden.
Beeinflusst vom AntLion-Modmic.
Download: modmic-simple.stl
Wie man mit Fizz Drachen stiehlt
Perfekte Reaktionen: Erst in den Drachen hineinspringen, dann herausspringen, mit Zhonyas Karthus Angriffe überleben und dann auch noch seiner Ulti ausweichen. Ich finde, das ist ein gutes Beispiel dafür, warum man ein Spiel wie LoL immer und immer wieder spielen kann und was man dabei im Kleinen lernt.
Vortrag: Wie LoL für besseres Spielerverhalten sorgt
Das Video des Vortrags, dessen Zusammenschrieb ich bereits verlinkte. Jeffrey Linn erklärt die Bemühungen Riots, den negativen Einfluss von pöbelnden Spielern auf die anderen zu verringern. Ziemlich interessant, Zahlen zu den auch selbst gespürten gewaltigen Auswirkungen dieser Experimente zu sehen.
Schweigen als Taktik
Nachtrag zu Lügen der Spielehersteller: Wenn Spielehersteller mit ihren Lügen auffliegen, müssen sie ja auch damit umgehen. Rock, Paper, Shotgun zeigt in einem Artikel über Maxis und SimCity, wie die das bei ihrer Lüge über die vermeintliche Berechnung von Zeug in der Cloud und dem damit angeblich notwendigen Always-On-Modus machten:
EA and Maxis simply ignored all those emails. Sites may have received a, “We’re waiting for a response,” from their regional PRs, but that was it. And so if you’re running GamePow.com, and you’ve decided you can’t run RPS’s anonymously sourced story without giving EA a response, ta-da – no story on GamePow. And EA knows that.
Leichte Software - Eine Definition
Martin hat in seinem Blog einen englischsprachigen Artikel What makes a “lightweight” desktop environment lightweight? geschrieben. In ihm kommt er zu dem Schluss, dass das Attribut "leichtgewichtig" willkürlich sei und eigentlich keine Bedeutung habe.
Ich mag den Artikel. Martin tut so, als würde er den Begriff nicht verstehen, und ich glaube, dass er sich da bewusst seiner eigenen instinktiven Deutung des Begriffes widersetzt - und er übersieht völlig die mich sehr erheiternde Ironie darin, wenn ausgerechnet ein KDE-Entwickler mit dem Bild leichter Software nichts anfangen kann (was ich tatsächlich nicht böse meine). Aber zusammen mit seinem Ausschlussverfahren, das ziemlich gut beschreibt, was leichte Software ist (nur zum gegenteiligen Schluss kommt), und den Kommentaren ergibt sich ein gutes Gesamtbild, das in meinen Augen den Begriff wirklich schön zeichnet. Ich nehme das mal und mische es hier mit meiner eigenen Definition.
1. Leichte Software ist subjektiv
Offensichtlich geht es nicht um das Gewicht der Software und nicht um die Größe des Codes. Software mit einem Gewicht zu belegen kann angesichts ihrer inhärenten Gewichtslosigkeit nur ein emotionaler Begriff sein, der eine Brücke schlägt zu Erfahrungen im rl. Und das ist ein guter Anhaltspunkt bei der Deutung des Begriffes. Wenn etwas im echten Leben schwer ist, tragen wir schwer daran, haben Probleme, es zu bewegen, beschleunigt es nicht so schnell wie ein leichteres Objekt mit der gleichen Antriebskraft; alles geeignete Analogien zu unserer jeweiligen subjektiven Erfahrung mit Software.
Martin begab sich auf die Suche einer festen Definition von leichter Software und scheiterte daran, eine solche zu finden. Wenn Software auf der und der Hardware so und so gut läuft, dann ist die Software leichtgewichtig - das wird man seltenst irgendwo lesen. Da es ein Attribut ist, das die Bewertung des Nutzers wiedergibt, ist es für jeden Nutzer eine andere Hardware und eine andere Eigenschaft, die das Attribut rechtfertigt. Das kann der Start der Software selbst sein: Wenn eine Desktopumgebung mehrere Sekunden zum Starten braucht, fühlt sich das nicht schnell, nicht leicht an. Es kann aber auch wesentlich weiter gehen. Es kann sogar technisch versierte Nutzer geben, welche die Abhängigkeiten oder den Code selbst heranziehen - das dürfte die Ausnahme sein, soll hier aber Beispiel dafür sein, wie subjektiv die Klassifikation sein kann.
2. Leichte Software ist effizient
Aber es gibt durchaus offizielle Definitionen der Benutzbarkeit von Software, die mit dem Begriff leichtgewichtiger Software verknüpfbar sind. Nach ihnen hat Martin seiner Beschreibung nach nur nicht gesucht und sie auch nicht zufällig gefunden.
Sie verbirgt sich in Effektivität, Effizenz und Nutzerzufriedenheit, dem Dreiklang der HCI nach DIN ISO 9241.
Effektivität:
Die Möglichkeit, mit dem Werkzeug eine Aufgabe überhaupt zu erledigen.
Effizienz:
Wie schnell und wie einfach die Aufgabe zu erledigen ist.
Nutzerzufriedenheit:
Der Begriff erklärt sich selbst, wird von den vorherigen Faktoren beeinflusst, aber nicht alleine von ihnen bestimmt.
Eine Kategorisierung von Software als leicht ist nun eine Einstufung dieser Software in der zweiten Kategorie, Effizenz. Denn vergleicht man zwei verschiedene Programme und hält das eine für leichtgewichtig, das andere aber nicht, impliziert man damit meist, dass beide der gleichen Aufgabe dienen. Effektivität kann es also nicht sein. Und Zufriedenheit ist zuwenig mit der eigentlichen funktionalen Eigenschaft der Software verknüpft, um das zu beschreiben (auch wenn das sicher mit hereinspielt). Es geht also darum, wie einfach und wie schnell etwas zu machen ist. Und klar: Geht etwas mit wenigen Klicks in einer überschaubaren Oberfläche und ohne störende Ruckler, geht es in der Regel effizienter, als sei dem nicht so. Und genau das kann leichte Software sein: Solche, die nicht ruckelt und solche, die eine Aufgabe schnell und einfach erledigen lässt.
3. Was leicht ist, wird relativ zur Hardware definiert
Wenn eine Desktopumgebung dazu führt, dass der Browser nur träge reagiert - dieser aber unter einer anderen annehmbar schnell läuft - ist sie sicher nicht leicht. Dieses Phänomen kann ich wunderbar auf dem Thinkpad R50 mit Unity und E17 beobachten. Während sich unter Unity alles zäh und träge anfühlt, beim Fenstermanagement, beim Aufruf des Dashs und den Hovereffekten des Docks, aber auch beim Surfen im Browser, ist es unter E17 gut erträglich, flüssig sogar, sodass man einwandfrei mit ihm arbeiten kann (ich hatte ihn z.B. auf dem ictf dabei). Offensichtlich ist Unity derart fordernd, dass die Oberfläche langsam gerendert wird und für die eigentliche Aufgabe nicht genug Ressourcen übrig bleiben. Das Gegenteil leichter Software.
4. Leichte Software hat keinen (wahrnehmbaren) bloat
Aber auch, wenn die GUI der Software viele Elemente hat und überladen wirkt, kann das zu dem Nutzereindruck führen, nicht leichtgewichtig zu sein. Das war nebenbei ja schon immer eine Lektion, die KDE nicht lernen wollte. Zum einen, weil leichte Software ein emotionaler Begriff und eine Analogie ist, zum anderen, weil es um die Effizenz beim Ausführen einer Aufgabe geht, ist es nicht alleine Geschwindigkeit der Software - eine Kerbe, in die Martin gerne schlägt, wenn er von Optimierungen für neue Hardware redet. Es geht um die Aufgabe und den Weg dahin, und eine klar steuerbare (noch so ein HCI-Begriff) GUI hilft dem Nutzer dabei, eine Aufgabe effizient zu erledigen.
Es geht hier wohlgemerkt nicht um Konfigurierbarkeit. IceWM und viele andere kleine, leichte Fenstermenager sind stärker konfigurierbar als jede Desktopumgebung. Trotzdem wirken sie leichter, schon weil sie in jeder Hinsicht schneller sind - und auch, weil ihre Konfigurationsmöglichkeiten in Textdateien versteckt sind.
Wobei sich das nicht auf GUIs beschränkt: Die Komplexität der Konfiguration und die Performance des Tools können auch bei Programmen mit Text-UI bewirken, nicht als leichtgewichtig wahrgenommen zu werden. Programmiersprachen sind gar ein völlig eigenes Kapitel.
Zusammenfassend: Leichte Software ist viel und wenig
Viele Programme können leicht wirken und viele Faktoren wirken sich hier aus. Der Eindruck kann sich ergeben, wenn etwas besonders flüssig läuft. Eine gute Energieeffizienz kann helfen, wenn der Nutzer gerade darauf achtet, z.B. weil unter Linux im Gegensatz zu Windows der Lüfter des Laptops nur in Ausnahmefällen zu hören ist oder der Akku länger hält. Wenn Software auf vielen alten System läuft, ist sie leicht, bzw diese ist es, die auf der alten Hardware am besten/schnellsten/flüssigsten läuft - aber nicht solche Software, die sich erstmal an einem 5-minütigen Splashfenster abrackert (übrigens ein Anti-Pattern in der Interfacegestaltung).
Das kann man umdrehen: Wenn ein Programm eine simple, klare Oberfläche mit wenigen Elementen hat, kann dies den Eindruck leichter Software hervorrufen. Verstärkt noch, wenn der Stil der Software schlicht ist - und meinem Eindruck nach insbesondere, wenn die Oberfläche zwar schlicht, aber gleichzeitig hübsch und auch noch responsiv ist. Sind die Hardwareanforderungen gering, ist Software leicht. Erfordert die Software wenig Vorwissen, ist die Software ebenfalls leicht - auch so kann man den Begriff anwenden, wobei hier sich leicht als einfach mit leicht als leichtgewichtig vermengt
Man kann das alles in eine vereinfachende Faustregel als Fazit zusammenpacken: Läuft Software schnell auf alter und neuer Hardware des Nutzers und hat keine Oberfläche, die eine gegenteilige Atmosphäre schafft (z.B. durch langsame Animationen oder der Komplexität des Workflows), dann wird sich beim Nutzer der Eindruck ergeben, dass die Software leichtgewichtig ist.
Ruby/Sinatra-Anwendung auf AppFog laufen lassen
Beim letzten mal war die versuchte Nutzung von Cloudhosting mit Heroku ein Reinfall. Relativ viel Arbeit für ein Scheitern an der Performance. Doch es gibt Alternativen zu Heroku, und AppFog ist eine, die mir sehr gut gefällt.
Auch AppFog unterstützt einen kostenlosen Account, bietet aber wesentlich mehr als Heroku: 2 GB statt 512 MB Ram, 8 Instanzen statt einem Worker und 8 mögliche sogenannte Services, darunter verschiedene Datenbanken. Es gibt auch Einschränkungen, die bei Heroku nicht erwähnt werden: 5 GB Traffic im Monat und ein Maximum von 100 Requests pro Sekunde. Unterschiedlich sind die Datenbanklimits und das Accountmodell: 100 MB bei AppFog gegen 10k Reihen bei Heroku, und AppFogs Ressourcen gelten accountweit, Herokus pro Anwendung. Völlig entfällt die ziemlich kritische Beschränkung, keine Hintergrundthreads laufen lassen zu können.
Wie gesagt, ich halte das AppFog-Angebot für wesentlich besser.
Instanz einrichten
Doch nicht nur das Hosting selbst ist besser, auch die Dokumentation drumrum gefiel mir besser. Sie ist auch schnell zusammengefasst. Statt direkt mit git wird mit einem Tool namens af gearbeitet:
gem install af af login
Vom Kontrollzentrum kann die Beispielanwendung als .zip heruntergeladen werden. Mit ihr wird auch schnell klar, was sonst noch zu tun ist. Wieder muss eine Gemfile angelegt werden. Meine:
source :rubygems gem "sinatra" gem "thin" gem 'pg' gem 'json' gem 'nokogiri' gem 'rest-client' gem 'haml
Ein
bundle install
später kann die Anwendung per
af update APPFOG-SERVERNAME
hochgeladen werden. Die app.rb kann mit jeder anderen Datei ersetzt werden, welche Datei ausgeführt werden muss, wird durch das require 'sinatra'
erkannt - sehr nett!
Datenbank aktivieren
Da die Anwendung vom letzten mal schon für PostgresSQL angepasst war, blieb das natürlich als Datenbank gesetzt. Die Datenbank kann im Kontrollzentrum als Service aktiviert und dort benannt werden. Dann werden die Einloggdaten als Umgebungsvariable der Anwendung gegeben, und diesmal gibt es tatsächlich ordentlichen Beispielcode (mit dem kleinen Fehler, dass dort im Original :username statt :user steht):
services = JSON.parse(ENV['VCAP_SERVICES']) postgresql_key = services.keys.select { |svc| svc =~ /postgresql/i }.first postgresql = services[postgresql_key].first['credentials'] postgresql_conn = {:host => postgresql['hostname'], :port => postgresql['port'], :user => postgresql['user'], :password => postgresql['password'], :dbname => postgresql['name']} @db = PG.connect(postgresql_conn)
Ansonsten gelten natürlich die gleichen Hinweise wie bei Heroku, wenn von sqlite aus umgestellt werden muss.
Gut funktionierte bei Heroku der Zugriff auf die Datenbank von außen. Auch bei AppFog ist das gut gelöst, wobei ich die Lösung erst finden musste. Das Stichwort ist Tunnelling:
gem install caldecott af services af tunnel DATENBANKNAME
Fazit
AppFog hatte natürlich den Vorteil, dass durch den vorherigen Versuch mit Heroku mir ziemlich klar war, wie das alles funktionieren müsste - reduzierte Verwirrung führt schnell zu einem besseren Eindruck. Aber auch ohne diesen Vorteil ist AppFog meiner Meinung nach klar die bessere Wahl:
- Wesentlich umfangreicheres kostenloses Angebot...
- ...mit tatsächlich deutlich besserer Performance.
- Klarer strukturierte Dokumentation, inklusive Beispielcode für die Datenbankanbindung (wie kann sowas fehlen?).
Aber der wichtigste Vorteil von AppFog ist, dass meine Anwendung hier funktionierte und auf Heroku nicht. Und das lag höchstwahrscheinlich am Serverstack und damit an Heroku, nicht an der Anwendung selbst (wie erwähnt konnte ich Herokus Analysetool nicht testen). Rsspusher trägt sich bei verschiedenen PuSH- bzw rssCloud-Hubs als Abonnent ein, und dieses Eintragen muss bei beiden Protokollen jedes mal bestätigt werden, indem von dem Hub ein GET an rsspusher geschickt wird, wobei die so gesendete Challenge zurückgegeben werden muss. Das war auf dem Entwicklungsrechner kein Problem, das war auf AppFog kein Problem, aber unter Heroku lief das jedes mal in ein das Zeitlmit von 2 bzw 3 Sekunden, weil die Anfrage laut Log im Heroku-Stack alleine solange hängen blieb. Ich weiß nicht, ob das an dem einzelnen Worker hing (eigentlich ist das kein Grund, ein Worker kann mehrere Anfragen parallel bearbeiten), aber das war definitiv kein guter Eindruck.
Jeffrey Lin (Riot) über Spielerverhalten
Lin briefly shared, for the first time, just a few of the results from the Optimus study. One interesting finding was that showing a red message about negative behavior during the loading screen lead to a much larger decrease in toxic behaviors (in terms of attitude displays, abuse, and offensive language) than did the exact same message in a white font. Additionally, showing a blue message about positive, cooperative behavior during the loading screen also lead to a decrease in a negative behavior, while no effect was observed for the same message in white. And, interestingly, when the question “Who will be the most sportsmanlike?” (a positive behavior message) was presented in red, the toxic behavior metrics actually all increased.
Eine gute Zusammenfassung samt weiterführenden Informationen über Riots Bemühungen, bei League of Legends das Spielerverhalten in positive Bahnen zu lenken. Besonders seit dem Honor-System (man kann Spieler nach dem Spiel für gutes Verhalten Auszeichnungen geben) fühlt sich das Spiel größtenteils wesentlich angenehmer an.
Auf den Gedanken, dass hinter den Farben der Ladebildschirmmeldungen experimentelle Ergebnisse stecken könnten, bin ich allerdings bisher nicht gekommen.
Rsspusher
Rsspusher ist für mich etwas in letzter Zeit ungewöhnliches: Ein Projekt ohne GUI, mehr ein Service als eine Webseite oder ein Programm. Schickt man ein json-Objekt mit der URL einer oder mehreren Webseiten und eine Callback-URL, wird rsspusher neue Einträge auf den ersten URLs an den Callback schicken, falls diese einen RSS-Feed haben (oder einer sind).
Besser erklärt ist das auf der wunderschön gestalteten Demoseite.
Zwei verschiedene Motivationen führten dazu, dass ich dieses Tool baute.
Zum einen funktioniert der Bau des Freundes-Aktivitätenstreams im dsnblog derzeit, indem der eine Blog den Feed des anderen zieht. Doch wie soll ein Blog mitkriegen, dass der andere neue Artikel hat? Ich wollte keinen Code schreiben, der alle paar Minuten den Feed zieht und auf neue Einträge prüft, weshalb ich anfing, pubsubhubbub zu implementieren. Der Code wird viel schöner, wenn der eine dsnblog jedes mal per POST benachrichtigt wird, wenn der andere einen neuen Eintrag schreibt. Und eigentlich sollte das mit jedem beliebigen Feed funktionieren, selbst wenn sie wie auch immer funktionierenden keinen Hub angeben und anpingen. Eigentlich sollte man sich in diesem Projekt gar nicht darum kümmern müssen, wie man an die Information kommt, dass es ein Update gab - und genau diese Auslagerung, das ist rsspusher.
Zum anderen wird Google Reader ja bald abgeschaltet, weshalb auf dem eigenen Server laufende RSS-Reader mehr Aufmerksamkeit bekommen und sicher auch einige neue gebaut werden. Baut man so etwas selbst, ist die Polling-Infrastruktur zum Holen der Feeds - und das Verwalten von pubsubhubbub- und rsscloud-Abonnements - ein nicht kleiner Teil der Aufgabe. Vielleicht hilft es jemanden, wenn rsspusher das übernimmt oder kann zumindest etwas Hilfe aus dem Code ziehen.
Im Grunde ziemlich ähnlich zu superfeedr, nur frei und selbsthostbar und nicht ansatzweise so ausgereift. Ich hatte Spaß, das zu bauen, und nebenbei rausbekommen, warum das pubsubhubbub-Plugin für Serendipity wahrscheinlich nicht funktionierte. Netter Bonus: Samstag nachmittag habe ich es als Submission bei Hackernews eingereicht und als ich nachts wiederkam, war es auf der Frontpage (unten, und bis ich meinen Kommentar fertig geschrieben hatte, war es auf Seite 2 und der Kommentar blieb daher unbeachtet, aber trotzdem toll). Gehörte zu den Dingen, die ich mal hinbekommen haben wollte.
Ruby/Sinatra-Anwendung für Heroku anpassen
Heroku ist eine Cloud-Plattform und war eine ganze Weile die einzige mir bekannte Plattform mit einem kostenlosen Tarif (ohne behaupten zu wollen, dass es damals nichts anderes gab). Da mir Ruby und besonders Sinatra sehr gut gefällt und Heroku für Ruby eine Weile der Cloudhoster-Vorzeigekandidat war, wollte ich schon vor einiger Zeit eine Anwendung von mir dort laufen lassen. Damals scheiterte ich - das ganze Ruby-Universum war mir noch zu neu - aber inzwischen habe ich ein anderes Projekt erfolgreich portiert. Man muss allerdings einiges beachten, was genau halte ich hier mal fest.
Alles hier gilt für Ubuntu 12.04.
Heroku einrichten
Herokus Seite ist der einfache Part. Auf https://www.heroku.com/ einen Account anlegen und der Anleitung folgen:
wget -qO- https://toolbelt.heroku.com/install-ubuntu.sh | sh # Heroku-Tools installieren heroku login # einloggen und public ssh-keys hochladen
Nun der rubyspezifische Teil (diese Anleitung). Für die Verwaltung der gems muss eine Datei Gemfile im Anwendungsverzechnis angelegt werden. Der Inhalt:
source :rubygems gem 'sinatra' gem 'pg' # die weiteren genutzten gems
Wer aus der Rails-Welt kommt, kennt das wohl. Die Datei dann auch nutzen:
bundle install
Außerdem fehlt noch die config.ru mit diesem Inhalt:
web: bundle exec rackup config.ru -p $PORT
Damit sind die benötigten Dateien zusammen. Dies alles nun in git festhalten und heruko übergeben:
git init git add . git commit -m "init" heroku create git push heroku master
Um später Updates an heroku zu sende, diesen Schritt ohne git init
und heroku create
ausführen
Postgresql installieren
Leider kann heroku nicht die von mir bevorzugte SQL-Datenbank nutzen, sqlite. Stattdessen muss man Postgresql nutzen, was mir eigentlich gar nicht passte - mir sind die nicht-dateibasierten Datenbank zu konfigurationslastig. So ist auch postgresql etwas knifflig einzurichten. Immerhin sollte der Wechsel der Performance der Anwendung gut tun.
Auf Heroku ist die postgresql-Datenbank schnell aktiviert:
heroku addons:add heroku-postgresql:dev
Um aber den Code weiter lokal testen zu können und den Datenbank-Remotezugriff nutzen zu können, muss Postgresql auch lokal installiert werden. Dafür installiert man das Paket postgresql. Die Datenbank muss aber noch konfiguriert werden. Am einfachsten ist dieser Weg:
sudo -u postgres createuser --superuser $USER sudo -u postgres psql postgres=# \password $USERNAME # des Hauptnutzers, unter dem entwickelt wird postgres=# \q createdb $USER
Hier wird eine Datenbank so eingerichtet, dass der Hauptnutzer sich mit einem psql in die Datenbank einwählen kann.
Datenbankcode für Postgresql anpassen
Nun muss noch der Code angepasst werden. Wer hier ein ORM nutzt, findet dafür in der Doku Code. Wer wie ich direkt mit SQL-Statements arbeiten will, der hat es etwas schwerer. Funktionierenden Beispielcode fand ich gar nicht.
Zuerst braucht man den Datenbankpfad. Ein
heroku config | grep HEROKU_POSTGRESQL
sollte einen String der Form postgres://USERNAME:PASSWORD@ec2-107-...-213.compute-1.amazonaws.com:5432/d9...rnr
zurückgeben. Diesem können nun die Datenbankdaten entnommen werden.
Im Ganzen: Ich habe eine database.rb, vorher ein Wrapper für sqlite. Vorher:
class Database def initialize() begin @@db # create a singleton - if this class-variable is uninitialized, this will fail and can then be initialized rescue @@db = SQLite3::Database.new "rssnotifier.db" begin puts "creating Database" @@db.execute "CREATE TABLE IF NOT EXISTS watches( ... @@db.execute "PRAGMA foreign_keys = ON;" @@db.results_as_hash = true rescue => error puts "error creating tables: #{error}" end end end def getPages(subscribed) begin pages = [] @@db.execute('SELECT DISTINCT url FROM watches WHERE subscribed = ?', subscribed ? 1 : 0) do |row| pages.push(Page.new(row["url"])) end return pages rescue => error puts "error getting pages: #{error}" end end ...
Umgestellt auf postgresql:
class Database def initialize() db = URI.parse(ENV['DATABASE_URL'] || 'postgres://USERNAME:PASSWORD@ec2-107-...-213.compute-1.amazonaws.com:5432/d9...rnr') @db = PG::Connection.open(:dbname => db.path[1..-1], :user => db.user, :password => db.password, :port => db.port, :host => db.host, :sslmode => 'require') #@db = PG::Connection.open(:dbname => 'onli', :user => 'onli', :port => 5433) # lokaler Zugriff begin puts "creating Database" @db.exec "CREATE TABLE IF NOT EXISTS watches( .... rescue => error puts "error creating tables: #{error}" end end def getPages(subscribed) begin pages = [] @db.exec('SELECT DISTINCT url FROM watches WHERE subscribed = $1', [subscribed] ? [1] : [0]) do |results| results.each do |row| pages.push(Page.new(row["url"])) end end return pages rescue => error puts "error getting pages: #{error}" end end ...
Eine Liste der Änderungen:
- Kein Singleton für die Verbindung nutzen! Das führte zu ziemlich widerlichen SSL-Fehlern und es dauerte ewig, bis ich darauf kam, dass es daran lag (übrigens kein Heroku-spezifischer Bug).
- Die Datenbankkonfiguration wird aus der Datenbankurl geparst (abgeleitet aus der Doku). Da habe ich mir Beispielcode (ohne ActiveRecord) in der Doku und einen schöneren Weg, ohne Parsen des Datenbankpfades, erhofft.
- exec ersetzt execute.
- Man beachte den zusätzlichen |results|-Zwischenschritt.
- (Nicht im Code) Postgresql beherrscht kein INSERT OR REPLACE. Stattdessen erst ein UPDATE, dann ein INSERT ausführen.
- Die Parameterersetzung hat eine andere Syntax: $X statt ? und Übergabe eines einzelnen Arrays statt der einzelnen Argumente.
- Den Code zum Zugriff auf die lokale Datenbank habe ich der Einfachheit halber hier festgehalten (den muss man nämlich auch erstmal finden). Man beachte den Port, der nicht der Standardport ist!
Die Anpassungen an den SQL-Queries selbst ist nicht zu schlimm, größtenteils scheint sqlite3 eine Submenge von postgresql zu sein. Bei den Datumsfunktionen bin ich dagegen direkt auf Rubycode umgestiegen.
Lohnt das?
Durchaus ein Haufen Aufwand, vor allem ohne diese Anleitung. Für meine Anwendung hat sich das ganze nichtmal gelohnt, heroku war schlicht zu langsam und die mit meiner Anwendung kommunizierenden Dienste liefen immer(!) in Timeouts. Wenn der freie Plan nichtmal zum Testen ohne jegliche Last reicht, ist das kein gutes Zeichen. Um festzustellen, an welcher Stelle die Anwendung hakt, bietet heroku mit New Relic die laut Liste nötigen Daten, ebenfalls mit einem kostenlosen Tarif - aber um den zu aktivieren, wird trotzdem eine Kreditkarte gefordert. Die ich weder besitze noch zu diesem Zeitpunkt angeben wollen würde.
Und so reizvoll die Skalierbarkeit solch einer Cloudplattform auch ist: Die Preise sind heftig. Ein eigener Server hat da echte Vorteile.
Riots LoL-Nachfolger
Auf chewgame findet sich Riots Aprilscherz. Ziemlich großartig gemachtes 8-Bit-artiges Flashgame, eigentlich sogar zwei (wenn man mit Gentleman-Chogath den Regenbogen aufisst).
Cities XL Platinum - Scheitern an Technik
Eines muss man SimCity lassen: Es hat es geschafft, Aufmerksamkeit zu bekommen. Natürlich ist es keine Option, das Spiel zu kaufen, aber nach all der Simcity-Berichterstattung hätte ich durchaus Lust, eine Weile ein Städtebauspiel zu spielen. Da kam mir Cities XL Platinum gerade recht. Das ist ein SimCity-Klon, bei dem die Städte auf einer Weltkarte verteilt sind und miteinander handeln können, und sieht auf den ersten Blick sehr gut aus. Leider nur auf den ersten Blick.
Wie in SimCity legt man Wohn-, Industrie- und Bürogebiete an, dazu kommen Einkaufsgebiete. Zusätzlich gibt es Agrarbetriebe, dazu kommen später Hightech-Industrie und Manufakturen. Anders als in SimCity bekommt jedes Haus eine Straße, automatisch. Die Gebiete gibt es alle in unterschiedlicher Dichte, die Wohngebiete gibt es für vier unterschiedliche Bildungsstufen, die von verschiedenen Betrieben gebraucht werden.
In der mit natürlich erscheinenden Zoomstufe sieht es nicht schlecht, aber auch nicht richtig gut aus. Die Einstellungen stehen auf Hoch, man sieht, dass trotzdem kein Antialiasing aktiviert ist. Die Autos sind schon in dieser Zoomstufe schwarze Kästen.
Das Problem ist aber nicht die Grafik. Das Problem ist die Performance. Bei mir wurde das Spiel extrem zäh, als meine Stadt 50k Einwohner erreichte. Insbesondere reagierte das Menü kaum noch. Aber auch schon vorher lief es nicht wirklich gut, z.B. ruckelt das Zoomen extrem. Dafür ist meine Hardware zu gut, und die Auswirkungen der Stadtgröße macht klar, dass es nicht an meinem System liegt - es ist das Spiel, das nicht richtig skaliert.
So nah rangezoomt sieht es richtig gut aus. Der Truck zeigt eine der schönen Seiten des Spiels, der fährt gerade von der Stadtgrenze oder meinem Industriegebiet zu den Büros, wenn ich das richtig sehe - da scheint wirklich etwas simuliert zu werden, was in der Stadt passiert.
Andere kleine Ärgernisse wiegen das auf. Um eine Kreuzung mit einem Kreisel zu ersetzen, müssen alle angrenzenden Straßen abgerissen werden - und ein paarmal konnten sie dann nicht angeschlossen werden. Und Straßen durch größere zu ersetzen scheint selbst dann nicht zu gehen, wenn dafür genug Platz wäre.
Dazu fand ich nicht alle Informationen und Stellschrauben, die ich gerne hätte. So wurde ich immer wieder aufgefordert, für die Einkaufsgebiete die Produktion zu verringern, ohne dass ich herausgefunden hätte, wie das geht. Und als ich Buslinien legen wollte, musste ich anhand der Autos auf der Straße raten, wie die Verkehrsströme wirklich sind, statt per Overlay die richtigen Daten gezeigt zu bekommen (nebenbei: warum kostet eine voll ausgelastete Buslinie Geld, anstatt welches einzubringen?).
Das im Bild zu sehende Stadtcenter ist übrigens eine kleine Ausbaustufe. Ich war schon wesentlich weiter, aber als ich versucht habe zu speichern, hat das Spiel mir stattdessen den alten Speicherstand geladen und ein paar Sekunden danach den einzigen Autosave überschrieben. Tolle Idee, Speichern und Laden als kleine Icons in das gleiche Menü zu setzen.
Fast ironisch angesichts der Probleme mit der Stadtgröße ist, dass Cities XL einen Vorteil gegenüber SimCity hat: Wirklich große Karten. Wenn man die doch nur nutzen könnte...