Jack Reacher: Never Go Back
Der mittelmäßige Actionfilm Jack Reacher muss sich ganz ordentlich verkauft haben, denn es gibt einen zweiten Teil. In Never Go Back spielt wieder Tom Cruise den Ex-Militär Jack, der natürlich ein Problem zu lösen hat.
Diesmal geht um jemanden, den er besuchen wollte. Es ist Robin aus How I Met Your Mother (also Cobie Smulders), hier befördert zum Major, eine Telefonbekanntschaft. Doch statt im Büro zu sein ist sie im Gefängnis. Und die Armee sendet Killer, um sie – und Jack – zu töten. Denen wollen die beiden entkommen, die Hintermänner stürzen und eine junge Frau schützen, die sie unterwegs aufsammeln.
Im Gegensatz zu IMDB (Teil 1, Teil 2), Rotten Tomatoes (Teil 1, Teil 2) und Metacritics (Teil 1, Teil 2) fand ich den zweiten Teil besser. Auch er ist nicht komplett super: Tom Cruise kann oder durfte kaum einen Gesichtsmuskel bewegen und die Story hat einen merkwürdig belanglosen Bösewicht im Hintergrund. Aber es gibt hier funktionierende Actionszenen, die anders als im ersten Teil nicht merkwürdig zerschnitten sind (oh, ob da die deutsche DVD-Version kaputtzensiert war und sie deshalb nicht funktionierten?). Die Dynamik mit Robin und Jack ist sehr gut – beide mögen sich und kämpfen doch darum, sich vom anderen nicht unterbuttern zu lassen. Dazu funktioniert der Rahmen des Films einfach.
Denn die Gefahr der Situation wird immer deutlich, mit dem sie jagenden und überlegenen Hunter und dem gefährdeten Schützling. Dieses Katz- und Maus-Spiel und die Dynamik zwischen den drei Protagonisten trägt den Film gut. Und gerade der ausgesendete Bösewicht funktioniert: Der Film zeigt nämlich klar, dass er gefährlich ist und Tom Cruise eben kein unverwundbarer Supermann. Es gibt also Gefahr und Personen in Gefahr, die man schnell als schützenswert wahrnimmt. Daher gibt es tatsächlich Spannung.
Ich würde das ganze für einen kompetenten Actionfilm halten. Daher bin ich etwas verwundert, wie negativ die Kritiken sind.
PC-Kombo bekam ein neues Design
Die Seite zum PC-Bauen - das ist was pc-kombo nun sein soll. Vorher nannte ich sie immer einen Hardwareempfehler, was auch stimmt. Aber ich hatte erkannt, dass die Seite aus mehr besteht, aus drei Teilen: Eben dem Empfehler (der auch ein Konfigurator ist), aber auch aus einer Hardwaredatenbank und einem nützlichen Benchmark. Das sollte nun besser gezeigt werden.
Generell gibt es ein neues Design, das – glaube ich – etwas hübscher und professioneller aussieht (auch wenn es sicher noch nicht 100% fertig ist). Strukturell sind die Bereiche klarer unterteilt, jeder Bereich hat zudem seine eigene Startseite mit Erklärungen. Die Hauptstartseite führt auch nicht mehr direkt zum Konfigurator, sondern erklärt die Seite im Ganzen
So sieht die Seite jetzt aus:
So sah sie vorher aus:
Die Überlegungen
Das waren meine Überlegungen beim jeweiligen Abschnitt:
Der Konfigurator
Das alte Design wirkte für neue Benutzer etwas kompliziert. Eine Liste mit Button statt den Blöcken macht die Komponentenliste einfacher zu verstehen und auch klarer, wie man sie anpassen kann. Das neue Design sollte es auch vereinfachen, weitere Funktionen wie das freie Hinzufügen neuer Hardwarekomponenten (z.B. drei SSDs) umzusetzen.
Es sind nun weniger Blöcke, weniger Rahmen, wodurch die Seite mehr wie ein zusammengehöriges Ganze wirkt. Für Ordnung sorgt stattdessen die Gruppierung. Die Linien zwischen den einzelnen Komponenten aber sind wichtig, um beim Listenlesen das Auge zu führen.
Da ist auch viel im Hintergrund passiert. So kann man jetzt problemlos Komponenten hinzufügen, die keinen Preis haben. Oder Konfigurationen basteln, die inkompatibel sind – da wird jetzt nur noch gewarnt. Das ist praktisch, wenn Daten in der Hardwaredatenbank falsch sind oder wenn man eben aus Versehen einen inkompatiblen PC gebaut hat und das nun mithilfe der Seite korrigieren will.
Die Hardwaredatenbank
Was erst eine eigene Seite werden sollte ist nun doch in pc-kombo beibehalten worden. Es wäre einfach zu viel doppelte Arbeit gewesen - Preise und Benchmarkdaten sind bei der Datenbank ja ebenso wichtige Daten, und im Benchmark und Konfigurator braucht man die PC-Komponenten. Warum das also komplett auftrennen?
Die Übersichtslisten haben sich zwar verändert, folgen aber dem gleichen Prinzip: Eine Liste, in der jeder Listenpunkt eine PC-Komponente ist und zudem ein paar Daten angezeigt werden, wie die Anzahl der Prozessorkerne zum Beispiel. Obendrüber gibt es einen Filter. Wichtiger als das komplett umzuwerfen war es mir, die Performance zu verbessern: Vorher konnten lange Listen schonmal den Browser zum Schnaufen bringen. Jetzt laden die Seiten schnell.
Die Einzelseiten sind massiv überarbeitet. Ich wollte erreichen, dass sie viel besser aussehen, und dass sie so nützlich wie möglich sind.
Vorher waren fast alle Inhalte verschiedene und unterschiedlich große Blöcke, verteilt in einem Grid. Jetzt sind deutliche Blöcke nur noch die Spezifikationen, die nur ein Teil der Seite sind. Bilder, wenn vorhanden, sind oben. Bei Prozessoren und Grafikkarten gibt es dazu eine automatisiert erstellte Beschreibung samt Leistungseinschätzung, was ich für total praktisch halte. Dann die Preise und das Preisverlaufsdiagram, erst jetzt die technischen Spezifikationen, und schließlich Reviews. Reviews gab es vorher schon, aber nur als eine Liste von Links. Jetzt tragen die meisten Reviews ein Logo und alle zeigen ein Zitat, welches das Review zusammenfasst.
Der Benchmark
Hier hat sich am wenigsten getan.
Ich setze darauf, dass die neue Startseite mit den Erklärungen Besuchern schon hilft, zu verstehen was der Benchmark ist. Die Vergleichsfunktion poppt nun beim Drüberfahren mit kurzem Anweisungstext auf und die Komponenten gehen daraufhin in eine Seitenleiste. Neu ist, dass auf der Vergleichsseite nur die Benchmarks angezeigt werden, in denen alle der Vergleichsprozessoren oder -grafikkarten vorkommen. Entweder es gibt einen guten Vergleich in der Datenbank oder eben nicht, das schafft Klarheit. Und das gruppierte Balkendiagramm mit den Einzelbenchmarkdaten sieht nun (dank des Umstiegs auf apexcharts) besser aus, es wird auch in keiner Situation mehr unten abgeschnitten oder unscharf.
Technische Hintergründe
Eigentlich wollte ich die drei Teile der Seite jeweils in eine eigene Seite verfrachten, mit statischen Seiten wo möglich. Zwei Dinge hielten mich davon ab: Als ich die Hardwaredatenbank als statische Seite gebaut hatte wurde deutlich, dass die anderen Informationen wie Preise und Benchmarkbewertungen auch hier praktisch wäre. Und ich hatte viel Erfolg, pc-kombo zu optimieren. Es stellte sich raus, dass die Performanceprobleme oft nur bestanden, weil hier und dort ein Datenbankindex fehlte, oder Funktionen unnötigerweise aufgerufen worden, oder schnellere gems wie FastGettext noch nicht benutzt wurden. Aber auch, dass die Komponentenlisten gar nicht auf der Serverseite langsam waren, sondern das Javascript (eine alte Version von jplist) den Browser blockierte.
Ich bin also die Seite durchgegangen, mit dem Firefox-Netzwerkinspektor und Flamegraphs bewaffnet, und habe jede Seitenart durchoptimiert. Und zwar das erste Laden, bevor der Cache befüllt ist. Weil das ja auch Seitenbesucher trifft und sicher massiv stören würde. Erst danach kam die Entscheidung pro Redesign und Beibehaltung unter einem Dach, aber klarerer Strukturierung.
Dementsprechend ist pc-kombo immer noch eine Ruby/Sinatra-Anwendung, mit SQLite als Datenbank. Es gibt aber eine Reihe von Verbesserungen, der Artikel zum effizienteren Speichern von Zeitreihen zum Beispiel kommt natürlich aus dieser Überarbeitung der Seite. Und das Datenbankschema ist etwas anders, wodurch zum Beispiel bei der Hauptdatenbankabfrage ein Join weniger gebraucht wird.
Eine große Änderung gab es bei den Sessions. Die waren vorher sehr wichtig, zentral für die Funktion der Seite. Wer /build?price=800
besuchte bekam in seine Session ein neues Empfehlungsobjekt gespeichert, und alle weiteren Funktionen wie das automatisierte Wählen eines neuen Prozessors griff auf dieses Objekt zu. Das bedeutete, dass geteilte URLs unbrauchbar waren, wenn nicht vorher ein Permalink erstellt wurde. Und der Code sehr zustandsabhängig wurde. Der neue Ansatz ist, dass /build?price=800
direkt auf einen Permalink weiterleitet, und weitere Funktionen dann von diesen Permalink ausgehen - also zum Beispiel /permalinkid1234/customize/cpu
. Struktur! Die hilft, Javascript zu vermeiden (dazu im nächsten Abschnitt mehr). Und ist ein Ergebnis aus dem Werkeln an dem statischen Seitengenerator, an der alternativen Hardwaredatenbank.
Ich habe auch Funktionen rausgeworfen, die nicht funktioniert haben. Statt Reviews gab es vorher auf Produktseiten unten eine Kommentarfunktion, die einfach nicht genutzt wurde. Upvoten und Downvoten, das wurde ein bisschen genutzt, aber nicht genug um mit den Daten die Listen nach Nutzervorlieben zu sortieren. Also ist sowas nicht mehr drin. Wobei nicht alles, was nicht mehr da ist, wegbleiben soll. Zum Beispiel fehlt das Löschen von Komponenten aus der Buildliste einfach noch.
Designprinzipien
Das Design ist diesmal nicht komplett handgemacht. Meinem Eindruck nach profitiert das Ergebnis deutlich davon, auf jeden Fall war die Arbeit dadurch viel einfacher. Es basiert auf dem CSS-Framework Spectre. Ich hatte mir ein paar Alternativen angeschaut, Spectre blieb über, weil es relativ simpel und vernünftig aussah, die Dokumentation klar war und die Komponenten sowie Beispiele hübsch. Außerdem, das war mir wichtig (und gleich mehr dazu), braucht das Framework kein Javascript. Die Wahl kann man hinterfragen, wäre das derzeit aktiver entwickelte Bulma vielleicht besser gewesen? Naja, wechseln kann man immer, auch wenn es Arbeit wäre.
Strukturschaffen war eines der Hauptziele. Es gibt die Startseite /
. Dazu kommen die Bereichsseiten /builder/
, /components/
und /benchmark/
. Die weiteren Unterseiten folgen dieser Struktur. Das war intern schon vorher so, wurde aber weniger gezeigt. Diese Struktur vorher klar zu definieren half auch beim Design. So war klar, dass es oben eine Hauptnavigation geben muss, für die drei Bereiche. Die Navigation innerhalb des Bereiches gehört da aber nicht wirklich rein, stattdessen habe sie jeweils eine Breadcrumbnavigation. Ich bilde mir ein, dass das hilft die Navigationsstruktur flachzuhalten und so weniger verwirrend zu machen.
Javascript wurde vermieden, indem mehr mit eigenständigen Seiten gearbeitet wird. Vorher war die Empfehlungsansicht fast schon eine SPA. Extrembeispiel: Wenn die Liste zur Komponentenauswahl geladen werden sollte, scrollte der Viewport nach rechts und dort wurde per Ajax die Auswahlliste hineingeladen. Jetzt gibt es dafür schlicht eine eigene Seite. Es gibt immer noch Javascript, natürlich: Apexcharts für die Benchmarkdiagramme, das neue jplist zum Filtern von Komponentenlisten, und 26 Zeilen handgeschriebenes Javascript für die Benchmarkvergleichsfunktion. Aber das wars. Auch ohne Javascript funktioniert der Großteil der Seite nun.
Weitere Pläne
Fehlende Funktionen nachzurüsten sollte jetzt wohl der Hauptfokus sein. Deaktivieren von Komponentenkategorien (wenn man z.B. keinen Arbeitsspeicher wählen will, weil der aus dem alten PC kommen wird), Filter für die Liste bei der manuellen Auswahl von Komponenten, die Sortierung verbessern. Und im Backend gibt es auch noch einiges zu tun, wie mehr Verwaltungsoberflächen, was dann mir die Arbeit erleichtert um z.B. Daten zu korrigieren, wodurch im Endeffekt die Seite für Besucher besser funktionieren wird.
Was wahrscheinlich ebenso wichtig ist: Ich will mehr Funktionen haben, um bei der Komponentenauswahl zu helfen. Zum Beispiel ist jetzt schon neu, dass mittels eines kleinen Icons jeweils die Bestandteile eines Builds empfohlen werden. Das sind die Bestandteile des PCs, den ich derzeit generell empfehlen würde, wenn das eigene Geld möglichst sinnvoll eingesetzt werden soll und es keine Spezialanforderungen gibt. Aber da kann noch mehr gemacht werden, denn generell gibt es in der Datenbank schon eine Liste von Komponenten, die berücksichtigt werden sollen – um zum Beispiel Grafikkartenmodelle auszuschließen, deren Kühler schlecht ist. Das könnte auch bei der manuellen Auswahl sichtbar gemacht werden.
Church of the Cosmic Skull - Everybody's Going To Die
Direkt. Das ist wohl Rock mit Chorgesang und Hammondorgel. Irgendwo zwischen Colour Haze und Queen und Pop.
Spectre anpassen, trotz ReferenceError
Die Anleitung wie man das nette CSS-Framework Spectre manuell kompilieren und so anpassen kann ist nicht vollständig. Sie besagt:
npm install gulp build
Nach vorherigem Herunterladen der Quellcodedateien natürlich.
Stattdessen musste ich so vorgehen:
npm install npm-install-peers npm install
Danach warf npx gulp build
aber einen Fehler:
fs.js:27 const { Math, Object } = primordials; ^ ReferenceError: primordials is not defined at fs.js:27:26 at req_ (/home/onli/spectre/node_modules/natives/index.js:143:24) at Object.req [as require] (/home/onli/spectre/node_modules/natives/index.js:55:10) at Object.<anonymous> (/home/onli/spectre/node_modules/graceful-fs/fs.js:1:37)
Stackoverflow kennt die Antwort: Man muss eine Datei npm-shrinkwrap.json mit folgendem Inhalt anlegen:
{ "dependencies": { "graceful-fs": { "version": "4.2.2" } } }
Und dann nochmal npm install
ausführen.
Also: Gulp wird nicht automatisch vollständig installiert, um es auszuführen bedarf es npx
. Die Version die spectre braucht ist aber sowieso inkompatibel mit neueren node-Version (in meinem Fall: 13.2.0). Deswegen der Fix per shrinkwrap-Datei.
Ich hasse die npm-Welt aus vollem Herzen.
Zeitreihen in SQLite speichern
Es ist eigentlich Unsinn, Daten wie Zeitreihen in SQLite zu speichern, da Timeseries-Datenbanken noch vor kurzem ein kleines Hype-Thema waren. Es gibt also einige Alternativen. Jedoch fand ich keine zu meinem Projekt passende. Sie alle sind entweder gedacht zur Analyse von Serverevents, benutzen Java, werden nicht mehr gepflegt oder sind zu komplex aufzusetzen. rrdtool kommt einer simplen Lösung noch am nächsten, aber die nötige Vorgabe der Taktung macht es für mich unpassend. Mein Ziel, jahrelange Preishistorien mit jeweils unterschiedlicher Taktung und auch mal einigen Lücken effizient zu speichern ohne einen Kubernetes-Cluster laufen lassen zu müssen scheint außerhalb der Javawelt zu selten zu sein.
Also blieb mein Provisorium bestehen. Eine SQLite-Datenbank mit dieser Tabelle:
CREATE TABLE IF NOT EXISTS priceHistory( id TEXT, date INTEGER, vendor TEXT, price REAL );"
Später kam noch ein Index dazu, weil die Performance ohne zu schlecht war:
CREATE INDEX priceHistory_ean_vendor ON priceHistory(id, vendor);
Das funktioniert! Es ist sogar trotz steigender Datenmenge auch einige Monate später noch schnell genug.
Diese steigende Datenmenge ist aber doch ein Problem: Mittlerweile ist diese Datenbank schon über 4GB groß, die Hälfte davon ist der Index. Das müsste kein Problem sein, Speicherplatz ist ja billig. Nur stimmt das nicht; nicht relativ zu den Serverkosten eines kleinen Projekts und angesichts möglicher zukünftiger Einschränkungen bei der Serverwahl, wenn die Datenbank weiter wächst. Und unbeschränktes Wachstum mit einer dann immer schwieriger handhabbaren Datenbankdatei bereitet mir Kopfschmerzen. Gut für die Performance kann die Lösung auf Dauer auch nicht sein.
Also durchforstete ich nochmal das Angebot an Zeitreihendatenbank und fand wieder nichts genau passendes. Zeit, einen Schritt zurückzugehen und zu überlegen, ob das nicht in SQLite bleiben und trotzdem etwas optimiert werden kann.
Strategie: Nur speichern was nötig ist
Die Daten dienen nur einem Zweck: Den Preisverlauf von Produkten anzuzeigen. Das sieht zum Beispiel so aus:
Wir zeichnen also im Grunde Strecken, wirklich dynamisch ändern sich die Preise nicht. Für eine Strecke brauche ich aber nicht mehr als zwei Punkte. Im gezeigten Diagramm sind es dagegen viele Punkte für jeden Abschnitt, da sich über eine längeren Zeitraum am Preis genau gar nichts getan hat. Das ist das erste Einsparpotential: Speichere nur, wenn sich der Wert geändert hat.
An der Datenbank muss man dafür nichts ändern. Die Optimierung kann rein im Code beim Abspeichern eines neuen Preises passieren. Trotzdem änderte ich den Index, passend zu den Daten:
CREATE TABLE IF NOT EXISTS priceHistory( id TEXT, date INTEGER, vendor TEXT, price REAL, UNIQUE(id, date, vendor) );"
Unnötige Doppelungen zu verhindern kann nur helfen.
Dann muss die Logik beim Datenzufügen angepasst werden. Vorher war das ein einfaches INSERT
. Jetzt sieht der Code in etwa so aus:
def storePrice(id:, price:, vendor:) # first we see whether the new entry differs from the last two, because if not we replace the last one. We need only two points to paint a trend line segment lastEntries = @db.execute("SELECT rowid, price FROM pmdb.priceHistory WHERE id = ? AND vendor = ? ORDER BY date DESC LIMIT 2", id, vendor) if price == lastEntries[0]['price'] && price == lastEntries[1]['price'] @db.execute("DELETE FROM pmdb.priceHistory WHERE rowid = ?", lastEntries[0]['rowid']) end # regardless what happened before, now we can just insert @db.execute("INSERT INTO pmdb.priceHistory(id, price, vendor, date) VALUES(?, ?, ?, strftime('%s','now'))", id, price, vendor) end
Ich fand, ein paar Visualisierungen machen das schneller klar.
Die naive Lösung hat einfach alles eingefügt.
Jetzt aber schaut der Code, ob die vorherigen Datenpunkte den gleichen Preis anzeigten. Wenn ja, verlängert er die Strecke, indem der letzte Datenpunkt gelöscht und stattdessen der neue (mit gleichem Preis, aber späterem Zeitpunkt) abgespeichert wird.
Wenn aber der Preis sich geändert hat bleiben die alten Datenpunkte bestehen und der neue kommt hinzu.
Sogar die bestehende Datenbank kann so verkleinert werden. Ich muss nur alle gespeicherten Datenpunkte entnehmen und mit dieser Strategie einzeln in eine neue Datenbanktabelle einfügen. Das Ergebnis behält tatsächlich seine Form, von der nun störenden Linienglättung mal abgesehen:
Und die Datenbank schrumpfte von 4.8GB auf 384MB, sehr ordentlich!
Weitere Kompressionsstrategien
Der nächste Schritt wäre das Bilden von Durchschnittswerten über definierte Zeiträume, Downsampling. Vielleicht kriege ich derzeit, je nach Händler, jede Stunde oder jeden halben Tag einen neuen Preis. Sind zwei Monate vergangen interessiert nur noch, wie teuer das Produkt durchschnittlich an einem Tag war. Nach 6 Monaten reichen die durchschnittlichen Preise in einer Woche. Nach einem Jahr der Durchschnittspreis in einem Monat.
Je nach Art der Zeitreihendaten ist diese Strategie deutlich besser, oder nur unnötig kompliziert. Hängt ganz davon ab wie oft sich die Preise bzw die Zeitreihendatenwerte ändern.
Sie lässt sich mit Code umsetzen, der in regelmäßigen Abständen durch die Datenbank geht und die Daten zusammenfasst. Es wäre toll, wenn es eine kleine Datenbank gäbe, der man solche Daten geben kann und die solche Konsolidierungen automatisch durchführt. Influxdb kann das zum Beispiel (wenn es entsprechend konfiguriert wird), aber ich würde eine Lösung bevorzugen, die nicht als zu wartende Infrastruktur auf einem Port läuft, sondern wie SQLite oder rrdtool einbindbar ist.
Vielleicht gibt es eine passende Datenbank und ich kenne sie nur nicht?
Update 20.09.2020: Ich stolpere gerade via HN über DuckDB, was eine interessante Alternative zu SQLite für diesen Anwendungsfall sein könnte. In diesem Blogartikel finden sich Beispiele.
Alita: Battle Angle
Auf den ersten Blick wirkt dieser Film sehr seltsam. Warum ist da ein offensichtlich animiertes Mädchen in einem Realfilm, noch dazu ein Scifi-Actionfilm, und warum mit diesen künstlichen Riesenaugen? Ist das Disney?
Wer Science-Fiction mag sollte Alita trotzdem eine Chance geben, denn er überrascht. Nach etwas Gewöhnungszeit wirkt sie nicht mehr so seltsam, tatsächlich ist die Figur im Rahmen des Möglichen hervorragend umgesetzt. Vor allem aber versucht der Film so einiges (aber Achtung, Spoiler), um den Zuschauer auf Alitas Seite zu ziehen, was dann auch absolut funktioniert.
Sie ist deplatziert in einer Welt, die nicht die ihre ist. Aber anstatt dort hilflos zu sein hat sie ein paar Überraschungen auf Lager. Es ist ja dann doch – anders als der Trailer suggeriert – ein Actionfilm, kein emotionales Drama. Aber eines, das seine CGI-Figur und die Schauspielerin dahinter ganz anders mischt, als Ghost in the Shell das gemacht hat.
Aber warum nur? Alita ist trotzdem ein guter Film geworden, aber eben: Trotzdem. Ich verstehe diese CGI-Entscheidung nicht. Wenn man sich die Frau anschaut, die das Motion Capturing gemacht hat, sieht sie sogar aus wie Alita. Nur halt echt. Warum dann nicht doch Ghost in the Shell folgen und ein echtes Gesicht nehmen, nur was ein menschlicher Körper nicht kann und nicht ist mit dem Computer erschaffen, anstatt so viele Zuschauer durch den Komplett-CGI-Hauptcharakter zu vergraulen? Denn egal wie gut Alita geworden ist, sie sieht keinen Moment real aus. Und entsprechend ist der Film an den Kinokassen gescheitert.
Das ist schade, denn wie gesagt: Man kann mitfiebern mit diesem Charakter, wie sie Hindernisse bewältigt, ihre Vergangenheit entdeckt und wie sich gegen Ende des Film eine Geschichte für den Nachfolger aufbaut. Wider Erwarten ist es keine herzlose künstliche Story, sondern ein sehr sorgfältig gemachter und überraschend emotionaler Film, der auch nicht zu kitschig wird, dabei einige sehr gute Actionszenen hat sowie im Kern eine gute Scifi-Story.
Surviving Mars
Surviving Mars ist ein Aufbauspiel in der harschen Umgebung des namensgebenden Planeten, umgesetzt von den Machern von Tropico 3 bis 5.
Es gibt eine Linuxversion, aber da sie bei mir nicht funktionierte spielte ich die Windowsversion via Proton.
Ähnlich wie in Tropico steht erstmal eine Art Szenarioauswahl an: Welche Nation, Kult oder Firma ist Sponsor der Mission, welches Profil hat der Kommandant, außerdem gibt es ein spielbegleitendes Mysterium mit Entscheidungsmöglichkeiten. In meinem ersten Durchlauf war mein Sponsor Europa (wodurch z.B. jeder Forschungsfortschritt Geld einbrachte), mein Kommandant ein Futurist (schnellere Freischaltung von Forschungsdurchbruchtechnologien) und das zufällig gewählte Mysterium drehte sich um eine KI, die in meinen Forschungstürmen wohnen wollte. Der Fokus meiner Kolonie war also eindeutig vorgegeben.
Zuerst aber ist wenig mit Forschung, sondern eine einzelne Rakete mit Vorräten (inklusive vorgebauter Gebäude) sowie Drohnen ist auf dem gewählten Marsterrain zu platzieren. Die Drohnen bringen dann ein Wirtschaftssystem in Gang: Produktionsgebäude wie Zementextraktoren wollen errichtet werden, die brauchen Stromerzeugung via Solarzellen, Windräder und magischen Sterling-Generatoren, Wasser muss abgebaut oder mit Verdunstungsanlagen generiert werden, womit Treibstoff hergestellt werden kann, mehr Drohnenhubs steuern weitere Drohnen und erweitern das Einflussgebiet - alles mit dem Ziel, eine erste kleine Kuppel für Kolonisten zu bauen. Die dann mit einer weiteren Rakete landen.
Denn nur Kolonisten können forschen und die fortgeschrittenen Rohstoffe herstellen, zum Beispiel Maschinenteile, die zur Wartung der Windräder oder zur Errichtung einiger anderer tollen Gebäude gebraucht werden. Bis das Wirtschaftssystem auf dem Mars diese Ressourcen herstellen kann ist der Spieler also auf Importe von der Erde angewiesen, die allerdings Geld kosten. Geld kommt automatisch durch den Sponsor oder durch Exporte von Metallen von Seltenen Erden, die aber auch nur Kolonisten abbauen können. Man sieht: Anfangs ist da durchaus Potential, sich in eine Sackgasse zu manövrieren. Die zu vermeiden und autark zu werden ist aber auch ein gutes Spielziel.
Zu erreichen ist dieses Ziel gar nicht so einfach, denn um alle benötigten Ressourcen abzubauen wächst die Kolonie auf dem Mars schnell auf eine beachtliche Größe, was gut verwaltet werden muss und nochmal mehr Ressourcen benötigt. Denn alle Gebäude verbrauchen Rohstoffe bei der regelmäßig notwendigen Wartung. Mir fehlte zum Beispiel zwischendurch auf einmal Metall, das vorher im Überschuss vorhanden war. Und ein andermal hatte ich mich mit der Essensproduktion verschätzt und meine Kolonisten hungerten etwas.
Erschwerend kam hinzu, dass Essen und andere Rohstoffe ja nicht nur vorhanden sein, sondern auch am richtigen Ort liegen müssen. Ich hatte z.B. noch Verpflegung, nur nicht in Reichweite der hungernden Kolonisten in der entfernteren Kuppel. Erst langsam brachten die Drohnen diese heran, immer von Lager zu Lager über die Einflussgebiete der mehreren Drohnenhubs, welche die Kuppeln verbanden. Erst später können die fliegenden Shuttle weite Transporte besser bewältigen, sie ermöglichen auch die Migration zwischen fernen Kuppeln.
Diese Migration nehmen die Kolonisten in Anspruch, wenn sie an einem anderen Ort besser aufgehoben wären. Denn jeder Kolonist hat eine Spezialisierung oder ist ein noch formbarer Generalist, und ein Wissenschaftler arbeitet lieber im Forschungszentrum als im Kasino, in dem sich der Generalist wohlfühlt. Jeder hat zudem eigene Bedürfnisse, wie das Glücksspiel im Kasino, und will eine eigene Wohnung, die in einer Residenz komfortabler als im platzsparenden Apartmentgebäude sind. Oder die negativen Eigenschaften greifen, so ist ein Einsiedler in Kuppeln mit mehr als 30 Einwohnern schnell unglücklich und will dann zurück zur Erde oder rebelliert. Auf dem Mars geborene Kolonisten – was in ausreichend komfortablen Kuppeln schnell geschieht, die Kinder werden auch schnell erwachsen – hingegen bleiben immer auf dem Mars und können durch Forschung viele Vorteile erhalten. Auch bei der Bevölkerungsverwaltung gibt es also immer viel Optimierungspotential.
So viele Facetten beachten zu müssen hat mir zwischendurch durchaus gut gefallen. Aber als ich jetzt nach der Weihnachtspause die Erweiterungen (die im Bundle dabeiwaren) antesten wollte fehlte mir etwas die Motivation, nochmal von vorne anzufangen. Denn es ist alles doch etwas gemächlich und mühselig. Von dem Spiel wird viel Mikromanagement und einiges an Wartezeit gefordert. Gleichzeitig sind die Survival-Elemente nicht so spannend, wie das erst wirkt. Man muss ja nur die Grundlagen (Essen, Sauerstoff, Wasser) abdecken und den Wirtschaftskreislauf am Laufen halten, was nur selten schwierig ist. Eigentlich nur während der seltenen Katastrophen wie Meteoritenschauern, die dann Gebäude und Leitungen beschädigen können. Die häufiger auftreten zu lassen wäre mir aber wieder zu stressig.
Surviving Mars wird bei mir wahrscheinlich ähnlich wie Cities Skylines nach etwas Wartezeit wiederentdeckt werden, wenn ich wieder Geduld für das Spiel übrig habe. Denn die Erweiterung Green Planet scheint etwas zu bringen, was vorher fehlte: Mit dem Terraforming Spielziele für große Kolonien. Das sollte mich dann doch bald wieder reizen.
Star Wars: The Rise of Skywalker
Diesmal war ich nicht ratlos, sondern fand nach etwas Zögern eine klare Position: Rise of Skywalker ist nicht gelungen.
Leichte Spoiler
Im Artikel zum Vorgänger prophezeite ich:
Aber ansonsten ist die Ausgangsposition in meinen Augen ziemlich einfach. Da das Imperium mit neuem Führer, dort die Überlebenden der Rebellion, die im nächsten Teil durch einen Aufstand der Massen im richtigen Moment den Sieg davontragen.
Volltreffer! Und dieser so offensichtliche Kniff ist gleichzeitig so richtig schlecht. Denn schon wieder passiert, was immer passiert: Die Schlacht läuft gut, dann agiert der Böse und sie kippt, alles sieht düster aus – doch da kommt die Erlösung. Wenn es so vorhersehbar ist, ist es dann noch ein Deus Ex Machina? Ein besonders billiges vielleicht?
Mich hat viel handwerkliches gestört. Die vielen Zitate für Menschen mit kurzer Konzentrationsspanne zum Beispiel: Unterschätze nie einen Droiden sagt die Prinzessin, zehn Minuten später wiederholt Rey das, völlig unpassend in einer Actionszene. Wohin verschwindet die alte Frau in der Endszene, warum läuft sie mitten in der Wüste vor einem verlassenen Haus herum? Warum buchstabiert der Oberbösewicht so deutlich, warum Rey ihr Vorhaben nicht umsetzen sollte – obwohl er will, dass sie genau das doch tut? Was will Finn Rey sagen, wie kann soetwas einfach vergessen werden?
Ich hatte aber auch schlicht unrecht: Ich dachte, der Verlauf der weiteren Story sei klar. Das stimmt nicht, weil alles aus dem Vorgänger ignoriert oder negiert wird. Der Kniff, dass Reys Eltern unbedeutend waren: Ätschie Bätsch, das Gegenteil ist der Fall. Eine neue Balance der Macht, mittels der Anziehung zwischen Rey und Kylo Ren? Vergiss es. Luke entsagt den Jedis? Quatsch, er hatte nur Angst und das jetzt im Jenseits erkannt. Der Oberböse war im keinem der Vorgänger angelegt und taucht daher total lächerlich aus dem Nichts auf.
Weil alles unmotiviert geschieht und komplett hanebüchen ist, scheitert erst der Anfang, es packt einen nicht. Dann wird es etwas besser, die Eckpfeiler einer Story stehen, fast wird es spannend. Doch drei Episoden in einem Film, entsprechend viele bemüht große Storymomente und (teils immerhin gute) Actionszenen: Unter diesem Ballast kracht dann alles ganz schnell zusammen. Skywalkers Aufstieg landet auf der Schnauze.