Translate App Strings to German #2330 (#2364)

* Translate App Strings to German #2330

--- src/status_im/translations/de.cljs
+++ src/status_im/translations/de.cljs
@@ -2,58 +2,67 @@

 (def translations
   {
-   ;common
+   ;;common
    :members-title                         "Mitglieder"
-   :not-implemented                       "nicht implementiert"
+   :not-implemented                       "!nicht implementiert"
    :chat-name                             "Chatname"
-   :notifications-title                   "Benachrichtigungen und Sounds"
+   :notifications-title                   "Benachrichtigungen und Töne"
    :offline                               "Offline"
    :search-for                            "Suche nach..."
    :cancel                                "Abbrechen"
    :next                                  "Weiter"
-   :type-a-message                        "Schreibe eine Nachricht..."
-   :type-a-command                        "Tippe ein Kommando..."
+   :open                                  "Öffnen"
+   :description                           "Beschreibung"
+   :url                                   "URL"
+   :type-a-message                        "Tippe eine Nachricht..."
+   :type-a-command                        "Tippe einen Befehl..."
    :error                                 "Fehler"
-
-   ;drawer
-   :invite-friends                        "Freunde einladen"
-   :faq                                   "FAQ"
+   :unknown-status-go-error               "Unbekannter status-go Fehler"
+   :node-unavailable                      "Kein laufender Ethereum-Knoten"
+   :yes                                   "Ja"
+   :no                                    "Nein"
+
+   :camera-access-error                   "Um den benötigten Kamera-Zugriff zu erlauben, gehe bitte in deine Systemeinstellungen und stelle sicher, dass Status > Kamera ausgewählt ist"
+   :photos-access-error                   "Um den benötigten Foto-Zugriff zu erlauben, gehe bitte in deine Systemeinstellungen und stelle sicher, dass Status > Fotos ausgewählt ist"
+
+   ;;drawer
    :switch-users                          "Benutzer wechseln"
-   :feedback                              "Haben Sie Feedback? Schütteln Sie einfach Ihr Mobilgerät."
-   :view-all                              "Alle ansehen"
    :current-network                       "Aktuelles Netzwerk"

-   ;chat
-   :is-typing                             "tippt"
+   ;;chat
+   :is-typing                             "schreibt"
    :and-you                               "und du"
    :search-chat                           "Chat durchsuchen"
    :members                               {:one   "1 Mitglied"
                                            :other "{{count}} Mitglieder"
-                                           :zero  "keine Mitglieder"}
-   :members-active                        {:one   "1 Mitglied, 1 aktiv"
-                                           :other "{{count}} Mitglieder, {{count}} aktiv"
-                                           :zero  "keine Mitglieder"}
+                                           :zero  "Keine Mitglieder"}
+   :members-active                        {:one   "1 Mitglied"
+                                           :other "{{count}} Mitglieder"
+                                           :zero  "Keine Mitglieder"}
+   :public-group-status                   "Öffentlich"
    :active-online                         "Online"
    :active-unknown                        "Unbekannt"
    :available                             "Verfügbar"
    :no-messages                           "Keine Nachrichten"
    :suggestions-requests                  "Anfragen"
    :suggestions-commands                  "Befehle"
-
-   ;sync
-   :sync-in-progress                      "synchronisiere..."
+   :faucet-success                        "Faucet-Anfrage wurde empfangen"
+   :faucet-error                          "Faucet-Anfragefehler"
+
+   ;;sync
+   :sync-in-progress                      "Synchronisiere..."
    :sync-synced                           "Synchronisiert"

-   ;messages
-   :status-sending                        "sendet..."
-   :status-pending                        "wird zugestellt"
-   :status-sent                           "Verschickt"
-   :status-seen-by-everyone               "Von Allen gesehen"
+   ;;messages
+   :status-sending                        "Sende..."
+   :status-pending                        "Ausstehend"
+   :status-sent                           "Gesendet"
+   :status-seen-by-everyone               "Von allen gesehen"
    :status-seen                           "Gesehen"
    :status-delivered                      "Zugestellt"
    :status-failed                         "Fehlgeschlagen"

-   ;datetime
+   ;;datetime
    :datetime-ago-format                   "{{ago}} {{number}} {{time-intervals}}"
    :datetime-second                       {:one   "Sekunde"
                                            :other "Sekunden"}
@@ -63,33 +72,36 @@
                                            :other "Stunden"}
    :datetime-day                          {:one   "Tag"
                                            :other "Tage"}
-   :datetime-multiple                     "mehrere"
    :datetime-ago                          "vor"
    :datetime-yesterday                    "Gestern"
    :datetime-today                        "Heute"

-   ;profile
+   ;;profile
    :profile                               "Profil"
-   :report-user                           "Benutzer melden"
+   :edit-profile                          "Profil bearbeiten"
    :message                               "Nachricht"
-   :username                              "Benutzername"
-   :not-specified                         "Nicht angegeben"
+   :not-specified                         "Nicht spezifiziert"
    :public-key                            "Öffentlicher Schlüssel"
-   :phone-number                          "Telefonnumer"
-   :email                                 "E-Mail"
-   :profile-no-status                     "Kein Status"
+   :phone-number                          "Telefonnummer"
+   :update-status                         "Aktualisiere deinen Status..."
+   :add-a-status                          "Einen Status hinzufügen..."
+   :status-prompt                         "Erstelle deinen Status. Die Verwendung von #hashtags kann anderen helfen, dich zu finden und mit dir über das zu reden, was dir auf dem Herzen liegt"
    :add-to-contacts                       "Zu Kontakten hinzufügen"
-   :error-incorrect-name                  "Bitte wählen Sie einen anderen Namen"
-   :error-incorrect-email                 "Inkorrekte E-Mail"
+   :in-contacts                           "In Kontakten"
+   :remove-from-contacts                  "Aus Kontakten entfernen"
+   :start-conversation                    "Beginne ein Gespräch"
+   :send-transaction                      "Sende Transaktion"
+   :testnet-text                          "Du befindest dich auf dem {{testnet}} Testnetzwerk
+    . Sende keine echten ETH oder SNT an deine Adresse"
+   :mainnet-text                          "Du befindest dich auf dem Mainnet. Echte ETH werden gesendet"

    ;;make_photo
-   :image-source-title                    "Profilfoto"
-   :image-source-make-photo               "Foto machen"
-   :image-source-gallery                  "Aus Galerie auswählen"
-   :image-source-cancel                   "Abbrechen"
+   :image-source-title                    "Profilbild"
+   :image-source-make-photo               "Aufnehmen"
+   :image-source-gallery                  "Aus Gallerie auswählen"

    ;;sharing
-   :sharing-copy-to-clipboard             "In Zwischenablage kopieren"
+   :sharing-copy-to-clipboard             "In die Zwischenablage kopieren"
    :sharing-share                         "Teilen..."
    :sharing-cancel                        "Abbrechen"

@@ -98,219 +110,258 @@
    :browsing-open-in-web-browser          "In Webbrowser öffnen"
    :browsing-cancel                       "Abbrechen"

-   ;sign-up
-
-   :contacts-syncronized                  "Ihre Kontakte wurden synchronisiert."
-   :confirmation-code                     (str "Danke! Wir haben Ihnen eine Textnachricht mit einem Bestätigungscode "
-                                               "geschickt. Bitte geben Sie den Code ein, damit wir Ihre Telefonnummer verifizieren können.")
-   :incorrect-code                        (str "Es tut uns leid, der Code war nicht korrekt, bitte erneut eingeben")
-   :generate-passphrase                   (str "Ich werde eine Passphrase für Sie generieren, damit Sie Ihren"
-                                               "Zugriff wiederherstellen oder sich von einem anderen Gerät aus einloggen können")
-   :phew-here-is-your-passphrase          "*Puh* das war schwer, hier ist Ihr Passphrase, *bitte aufschreiben und sicher aufbewahren! *Sie benötigen dies, um Ihren Account wiederherzustellen."
-   :here-is-your-passphrase               "Hier ist Ihr Passphrase, *bitte aufschreiben und sicher verwahren!*Sie benötigen dies, um Ihren Account wiederherzustellen."
-   :written-down                          "Stellen Sie sicher, dass Sie es sicher aufgeschrieben haben"
-   :phone-number-required                 "Tippen Sie hier, um Ihre Telefonnummer einzugeben & ich werde Ihre Freunde finden"
-   :intro-status                          "Chatten Sie mit mir, um Ihren Account einzurichten und Ihre Einstellungen zu ändern!"
-   :intro-message1                        "Willkommen bei Status.\nTippen Sie auf diese Nachricht, um Ihr Passwort einzurichten und loszulegen!"
-   :account-generation-message            "Eine Sekunde, ich muss wahnsinnig schwierige Berechnungen durchführen, um Ihr Konto zu generieren!"
-
-   ;chats
+   ;;sign-up
+   :contacts-syncronized                  "Deine Kontakte wurden synchronisiert"
+   :confirmation-code                     (str "Danke! Wir haben dir eine Textnachricht mit einem Bestätigungscode "
+                                               "gesendet. Bitte gib diesen Code an, um deine Telefonnummer zu verifizieren.")
+   :incorrect-code                        (str "Es tut uns leid, der Code war nicht korrekt, bitte gib ihn erneut ein")
+   :phew-here-is-your-passphrase          "Puh, das war anstrengend. Hier ist deine Passphrase. *Notiere sie dir und bewahre sie sicher auf!* Du wirst sie brauchen, um deinen Account wiederherzustellen."
+   :here-is-your-passphrase               "Hier ist deine Passphrase. *Notiere sie dir und bewahre sie sicher auf!* Du wirst sie brauchen, um deinen Account wiederherzustellen."
+   :here-is-your-signing-phrase           "Hier ist deine Signing Phrase. Du wirst sie benutzen, um deine Trtansaktionen zu verifizieren. *Notiere sie dir und bewahre sie sicher auf!*"
+   :phone-number-required                 "Tippe hier, um deine Telefonnummer zu validieren und ich werde deine Freunde finden."
+   :shake-your-phone                      "Du hast einen Bug gefunden oder hast einen Verbesserungsvorschlag? ~Schüttle~ einfach dein Handy!"
+   :intro-status                          "Chatte mit mir, um deinen Account einzurichten und deine Einstellungen zu ändern."
+   :intro-message1                        "Willkommen bei Status!\nKlicke auf diese Nachricht, um dein Passwort festzulegen und loszulegen."
+   :account-generation-message            "Gib mir eine Sekunde, ich muss wahnsinnig komplizierte Berechnungen tätigen, um deinen Account zu generieren!"
+   :move-to-internal-failure-message      "Wir müssen ein paar wichtige Dateien vom externen zum internen Speicher verschieben. Dafür brauchen wir deine Erlaubnis. In zukünftigen Versionen werden wir keinen externen Speicher mehr verwenden."
+   :debug-enabled                         "Der Debug-Server wurde gestartet! Du kannst jetzt *status-dev-cli scan* ausführen, um den Server von deinem Computer im selben Netzwerk zu finden."
+
+   ;;phone types
+   :phone-e164                            "International 1"
+   :phone-international                   "International 2"
+   :phone-national                        "National"
+   :phone-significant                     "Signifikant"
+
+   ;;chats
    :chats                                 "Chats"
-   :new-chat                              "Neuer Chat"
+   :delete-chat                           "Chat löschen"
    :new-group-chat                        "Neuer Gruppenchat"
-   :new-public-group-chat                 "Öffentlichem Gruppenchat beitreten"
+   :new-public-group-chat                 "Öffentlichem Chat beitreten"
    :edit-chats                            "Chats bearbeiten"
    :search-chats                          "Chats durchsuchen"
    :empty-topic                           "Leeres Thema"
-   :topic-format                          "Falsches Format[a-z0-9\\-]+"
+   :topic-format                          "Falsches Format [a-z0-9\\-]+"
    :public-group-topic                    "Thema"

-   ;discover
+   ;;discover
    :discover                              "Entdecken"
    :none                                  "Nichts"
-   :search-tags                           "Suchbegriffe"
-   :popular-tags                          "Beliebte Begriffe"
-   :recent                                "Kürzlich"
-   :no-statuses-discovered                "Kein Status gefunden"
-
-   ;settings
+   :search-tags                           "Tippe deine Suchbegriffe hier"
+   :popular-tags                          "Beliebte #hashtags"
+   :recent                                "Kürzliche Status"
+   :no-statuses-found                     "Keine Status gefunden"
+   :chat                                  "Chat"
+   :all                                   "Alle"
+   :public-chats                          "Öffentliche Chats"
+   :soon                                  "Bald"
+   :public-chat-user-count                "{{count}} Personen"
+   :dapps                                 "ÐApps"
+   :dapp-profile                          "ÐApp Profil"
+   :no-statuses-discovered                "Keine Status gefunden"
+   :no-statuses-discovered-body           "Wenn jemand einen\n Status erstellt, wirst du es hier sehen."
+   :no-hashtags-discovered-title          "Keine #hashtags gefunden"
+   :no-hashtags-discovered-body           "Wenn ein #hashtag beliebt\nwird, wirst du es hier sehen."
+
+   ;;settings
    :settings                              "Einstellungen"

-   ;contacts
+   ;;contacts
    :contacts                              "Kontakte"
    :new-contact                           "Neuer Kontakt"
-
-   :show-all                              "Alle Kontakte anzeigen"
-
-   :contacts-group-dapps                  "ÐApps"
-   :contacts-group-people                 "Leute"
+   :delete-contact                        "Kontakt löschen"
+   :delete-contact-confirmation           "Dieser Kontakt wird aus deinen Kontakten gelöscht"
+   :remove-from-group                     "Aus Gruppe entfernen"
+   :edit-contacts                         "Kontakte bearbeiten"
+   :search-contacts                       "Kontakte durchsuchen"
    :contacts-group-new-chat               "Neuen Chat starten"
+   :choose-from-contacts                  "Aus Kontakten wählen"
    :no-contacts                           "Noch keine Kontakte"
    :show-qr                               "QR-Code anzeigen"
-
-   ;group-settings
+   :enter-address                         "Andresse eingeben"
+   :more                                  "mehr"
+
+   ;;group-settings
    :remove                                "Entfernen"
    :save                                  "Speichern"
-   :change-color                          "Farbe ändern"
-   :clear-history                         "Verlauf löschen"
-   :delete-and-leave                      "Löschen und verlassen"
-   :chat-settings                         "Chateinstellungen"
+   :delete                                "Löschen"
+   :clear-history                         "Verlauf leeren"
+   :mute-notifications                    "Benachrichtigungen stummschalten"
+   :leave-chat                            "Chat verlassen"
+   :chat-settings                         "Chat-Einstellungen"
    :edit                                  "Bearbeiten"
    :add-members                           "Mitglieder hinzufügen"
-   :blue                                  "Blau"
-   :purple                                "Lila"
-   :green                                 "Grün"
-   :red                                   "Rot"
-
-   ;commands
-   :money-command-description             "Geld senden"
-   :location-command-description          "Standort senden"
-   :phone-command-description             "Telefonnummer senden"
-   :phone-request-text                    "Telefonnummer anfragen"
-   :confirmation-code-command-description "Bestätitungscode senden"
-   :confirmation-code-request-text        "Bestätigungscode anfragen"
-   :send-command-description              "Senden"
-   :request-command-description           "Anfrage senden"
-   :keypair-password-command-description  ""
-   :help-command-description              "Hilfe"
-   :request                               "Anfrage"
-   :chat-send-eth                         "{{amount}} ETH senden"
-   :chat-send-eth-to                      "{{amount}} ETH an {{chat-name}} senden"
-   :chat-send-eth-from                    "{{amount}} ETH von {{chat-name}} empfangen"
-
-   ;new-group
-   :group-chat-name                       "Gruppenname"
-   :empty-group-chat-name                 "Bitte geben Sie einen Namen ein"
-   :illegal-group-chat-name               "Bitte wählen Sie einen anderen Namen"
-
-   ;participants
-   :add-participants                      "Teilnehmer hinzufügen"
-   :remove-participants                   "Teilnehmer entfernen"
-
-   ;protocol
-   :received-invitation                   "Gruppenchateinladung erhalten"
-   :removed-from-chat                     "Aus dem Gruppenchat entfernt"
-   :left                                  "Links"
-   :invited                               "Eingeladen"
-   :removed                               "Entfernt"
+
+   ;;commands
+   :chat-send-eth                         "{{amount}} ETH"
+
+   ;;location command
+   :your-current-location                 "Dein aktueller Standort"
+   :places-nearby                         "Standorte in der Nähe"
+   :search-results                        "Ergebnisse durchsuchen"
+   :dropped-pin                           "Pin gesetzt"
+   :location                              "Standort"
+   :open-map                              "Öffne Karte"
+   :sharing-copy-to-clipboard-address     "Adresse kopieren"
+   :sharing-copy-to-clipboard-coordinates "Koordinaten kopieren"
+
+   ;;new-group
+   :new-group                             "Neue Gruppe"
+   :reorder-groups                        "Gruppen neu ordnen"
+   :edit-group                            "Gruppe bearbeiten"
+   :delete-group                          "Gruppe löschen"
+   :delete-group-confirmation             "Diese Gruppe wird aus deinen Gruppen gelöscht. Deine Kontakte bleiben hiervon unbeeinflusst"
+   :delete-group-prompt                   "Deine Kontakte bleiben hiervon unbeeinflusst"
+   :contact-s                             {:one   "Kontakt"
+                                           :other "Kontakte"}
+
+   ;;protocol
+   :received-invitation                   "Chat-Einladung erhalten"
+   :removed-from-chat                     "hat dich aus dem Gruppenchat entfernt"
+   :left                                  "hat die Gruppe verlassen"
+   :invited                               "eingeladen"
+   :removed                               "entfernt"
    :You                                   "Du"

-   ;new-contact
+   ;;new-contact
    :add-new-contact                       "Neuen Kontakt hinzufügen"
-   :import-qr                             "Importeren anhang QR-Code"
-   :scan-qr                               "QR-Code scannen"
+   :scan-qr                               "Scanne QR-Code"
    :name                                  "Name"
-   :whisper-identity                      "Identität flüstern"
-   :address-explication                   "Deine Adresse findest du in deinem Benutzerprofil"
-   :enter-valid-address                   "Bitte geben Sie eine gültige Adresse ein oder scannen Sie einen QR-Code"
+   :address-explication                   "Dein öffentlicher Schlüssel wird verwendet, um deine Adresse auf Ethereum zu generieren und besteht aus einer Folge von Zahlen und Buchstaben. Du findest ihn leicht in deinem Profil"
+   :enter-valid-public-key                "Bitte gib einen validen öffentlichen Schlüssen ein oder scanne einen QR-Code"
    :contact-already-added                 "Dieser Kontakt wurde bereits hinzugefügt"
    :can-not-add-yourself                  "Du kannst dich nicht selbst hinzufügen"
    :unknown-address                       "Unbekannte Adresse"

-
-   ;login
+   ;;login
    :connect                               "Verbinden"
    :address                               "Adresse"
    :password                              "Passwort"
-   :login                                 "Login"
+   :sign-in-to-status                     "Bei Status einloggen"
+   :sign-in                               "Einloggen"
    :wrong-password                        "Falsches Passwort"
-
-   ;recover
-   :recover-from-passphrase               "Mittels Passphrase wiederherstellen"
-   :recover-explain                       "Bitte gib die Passphrase für deinen Account ein, um den Zugriff wiederherzustellen"
+   :enter-password                        "Passwort eingeben"
+
+   ;;recover
    :passphrase                            "Passphrase"
    :recover                               "Wiederherstellen"
-   :enter-valid-passphrase                "Bitte geben Sie eine gültige Passphrase ein"
-   :enter-valid-password                  "Bitte geben Sie ein Passwort ein"
-
-   ;accounts
-   :recover-access                        "Zugriff wiederherstellen"
-   :add-account                           "Konto hinzufügen"
-
-   ;wallet-qr-code
-   :done                                  "Fertig"
-   :main-wallet                           "Hauptkonto"
-
-   ;validation
+   :twelve-words-in-correct-order         "12 Wörter in der richtigen Reihenfolge"
+
+   ;;accounts
+   :recover-access                        "Zugriff Wiederherstellen"
+   :create-new-account                    "Neues Konto erstellen"
+
+   ;;wallet-qr-code
+   :done                                  "Erledigt"
+
+   ;;validation
    :invalid-phone                         "Ungültige Telefonnummer"
    :amount                                "Betrag"
-   :not-enough-eth                        (str "Nicht genug ETH auf dem Konto"
-                                               "({{balance}} ETH)")
-   ;transactions
-   :confirm-transactions                  {:one   "Transaktion bestätigen"
-                                           :other "{{count}} Transaktionen bestätigen"
-                                           :zero  "Keine Transaktionen"}
+
+   ;;transactions
+   :confirm                               "Bestätigen"
+   :transaction                           "Transaktion"
+   :unsigned-transaction-expired          "Unsignierte Transaktion ist ausgelaufen"
    :status                                "Status"
-   :pending-confirmation                  "Bestätigung ausstehend"
    :recipient                             "Empfänger"
-
-   :one-more-item                         "Noch ein Objekt"
-   :fee                                   "Gebühren"
-
-   :value                                 "Wert"
-
-   ;:webview
+   :to                                    "An"
+   :from                                  "Von"
+   :data                                  "Daten"
+   :got-it                                "Erhalten"
+   :block                                 "Block"
+   :hash                                  "Hash"
+   :gas-limit                             "Gaslimit"
+   :gas-price                             "Gaspreis"
+   :gas-used                              "Gas verbraucht"
+   :cost-fee                              "Kosten/Gebühren"
+   :nonce                                 "Nonce"
+   :confirmations                         "Bestätigungen"
+   :confirmations-helper-text             "Bitte warte mindestens 12 Bestätigungen ab, um sicherzustellen, dass deine Transaktion sicher bearbeitet wurde"
+   :copy-transaction-hash                 "Transaktions-Hash kopieren"
+   :open-on-etherscan                     "Auf Etherscan.io öffnen"
+
+   ;;webview
    :web-view-error                        "Ups, Fehler"

-   :confirm                               "Bestätigen"
-   :phone-national                        "National"
-   :transactions-confirmed                {:one   "Transaktion bestätigt"
-                                           :other "{{count}} Transaktionen bestätigt"
-                                           :zero  "Keine Transaktion bestätigt"}
-   :debug-enabled                         "Debug-Server wurde eingeführt! Sie können nun Ihre DApp hinzufügen, indem Sie *status-dev-cli scan* von Ihrem Computer starten"
-   :share-qr                              "QR teilen"
-   :twelve-words-in-correct-order         "12 Wörter in richtiger Reihenfolge"
-   :remove-from-contacts                  "Von Kontakten entfernen"
-   :delete-chat                           "Chat löschen"
-   :sign-in                               "Anmelden"
-   :create-new-account                    "Neues Konto erstellen"
-   :sign-in-to-status                     "Zum Status anmelden"
-   :got-it                                "Verstanden"
-   :move-to-internal-failure-message      "Wir müssen ein paar wichtige Dateien vom externen auf den internen Speicher verschieben. Um dies tun zu können, brauchen wir Ihre Genehmigung. Wir werden in zukünftige Versionen keinen externen Speicher nutzen."
-   :edit-group                            "Gruppe bearbeiten"
-   :delete-group                          "Gruppe löschen"
-   :reorder-groups                        "Gruppen wieder ordnen"
-   :faucet-success                        "Absperranfrage wurde erhalten"
-   :choose-from-contacts                  "Aus Kontakten wählen"
-   :new-group                             "Neue Gruppe"
-   :phone-e164                            "International 1"
-   :remove-from-group                     "Von Gruppe entfernen"
-   :search-contacts                       "Kontakte durchsuchen"
-   :transaction                           "Transaktion"
-   :public-group-status                   "Öffentlich"
-   :leave-chat                            "Chat verlassen"
-   :start-conversation                    "Konversation beginnen"
-   :enter-valid-public-key                "Bitte geben Sie einen gültigen öffentlichen Schlüssel ein oder scannen Sie einen QR-Code"
-   :faucet-error                          "Absperranfrage-Fehler"
-   :phone-significant                     "Signifikant"
-   :phone-international                   "International 2"
-   :enter-address                         "Adresse eingeben"
-   :send-transaction                      "Transaktion senden"
-   :delete-contact                        "Kontakt löschen"
-   :mute-notifications                    "Benachrichtigungen stummschalten"
-
-
-   :contact-s                             {:one   "Kontakt"
-                                           :other "Kontakte"}
-   :group-name                            "Gruppenname"
-   :from                                  "Von"
-   :in-contacts                           "In Kontakte"
-
-   :shake-your-phone                      "Haben Sie einen Fehler gefunden oder einen Vorschlag? ~Schütteln~ Sie einfach Ihr Telefon!"
-   :status-prompt                         "Erstellen Sie einen Status, um anderen Menschen zu helfen, über die Dinge zu erfahren, die Sie anbieten. Sie können auch #hashtags nutzen."
-   :add-a-status                          "Einen Status hinzufügen ..."
-   :edit-contacts                         "Kontakte bearbeiten"
-   :more                                  "Mehr"
-   :no-statuses-found                     "Keine Status gefunden"
-   :swow-qr                               "QR anzeigen"
-   :delete-group-prompt                   "Dies wird Kontakte nicht beeinträchtigen"
-   :edit-profile                          "Profil bearbeiten"
-
-
-   :enter-password-transactions           {:one   "Bestätigen Sie die Transaktion durch Eingabe Ihres Passworts"
-                                           :other "Bestätigen Sie die Transaktionen durch Eingabe Ihres Passworts"}
-   :unsigned-transactions                 "Unsignierte Transaktion"
-   :to                                    "An"
-   :group-members                         "Gruppenmitglieder"
-   :estimated-fee                         "Geschätzte Gebühr"
-   :data                                  "Daten"})
+   ;;testfairy warning
+   :testfairy-title                       "Warnung!"
+   :testfairy-message                     "Du verwendest eine App Version, die aus einem Nightly Build stammt. Zu Testzwecken zeichnet diese Versions Sitzungsdaten auf, solange eine Wlan-Verbindung genutzt wird. Das bedeutet, dass all deine Interaktionen mit der App gespeichert werden (als Video und Logs) und von unseren Entwicklungsteam verwendet werden könnten, um mögliche Probleme zu untersuchen. Gespeicherte Videos/Logs enthalten keine Passwörter. Aufnahmen werden nur erstellt, wenn die App aus einem Nightly Build installiert wurde. Es wird nichts aufgezeichnet, wenn die App aus dem PlayStore oder TestFlight installiert wurde."
+
+   ;; wallet
+   :wallet                                "Wallet"
+   :wallets                               "Wallets"
+   :your-wallets                          "Deine Wallets"
+   :main-wallet                           "Haupt-Wallet"
+   :wallet-error                          "Fehler beim Laden"
+   :wallet-send                           "Senden"
+   :wallet-request                        "Anfragen"
+   :wallet-exchange                       "Tauschen"
+   :wallet-assets                         "Assets"
+   :wallet-add-asset                      "Asset hinzufügen"
+   :wallet-total-value                    "Gesamter Wert"
+   :wallet-settings                       "Wallet-Einstellungen"
+   :signing-phrase-description            "Signiere die Transaktion, indem du dein Passwort eingibst. Stelle sicher, dass die Wörter oben deiner geheimen Signing Phrase entsprechen"
+   :wallet-insufficient-funds             "Unzureichendes Kapital"
+   :request-transaction                   "Transaktion anfordern"
+   :send-request                          "Anfrage senden"
+   :share                                 "Teilen"
+   :eth                                   "ETH"
+   :currency                              "Währung"
+   :usd-currency                          "USD"
+   :transactions                          "Transaktionen"
+   :transaction-details                   "Transaktionsdetails"
+   :transaction-failed                    "Transaktion fehlgeschlagen"
+   :transactions-sign                     "Signiere"
+   :transactions-sign-all                 "Signiere alle"
+   :transactions-sign-transaction         "Signiere Transaktion"
+   :transactions-sign-later               "Später signieren"
+   :transactions-delete                   "Transaktion löschen"
+   :transactions-delete-content           "Transaktion wird von der 'Unsigniert' Liste entfernt"
+   :transactions-history                  "Verlauf"
+   :transactions-unsigned                 "Unsigniert"
+   :transactions-history-empty            "Noch keine Transaktionen in deinem Verlauf"
+   :transactions-unsigned-empty           "Du hast keine unsignierten Transaktionen"
+   :transactions-filter-title             "Filterverlauf"
+   :transactions-filter-tokens            "Tokens"
+   :transactions-filter-type              "Typ"
+   :transactions-filter-select-all        "Alle auswählen"
+   :view-transaction-details              "Transaktionsdetails anzeigen"
+   :transaction-description               "Bitte warte mindestens 12 Bestätigungen ab, um sicherzustellen, dass deine Transaktion sicher bearbeitet wurde"
+   :transaction-sent                      "Transaktion gesendet"
+   :transaction-moved-text                "Die Transaktion wird für die nächsten 5 Minuten in der 'Unsigniert' Liste bleiben"
+   :transaction-moved-title               "Transaktion verschoben"
+   :sign-later-title                      "Transaktion später signieren?"
+   :sign-later-text                       "Gehe in den Transaktionsverlauf, um diese Transaktion zu signieren."
+   :not-applicable                        "Nicht anwendbar für unsignierte Transaktionen"
+
+   ;; Wallet Send
+   :wallet-choose-recipient               "Empfänger auswählen"
+   :wallet-choose-from-contacts           "Aus Kontakten auswählen"
+   :wallet-address-from-clipboard         "Adresse aus Zwischenablage verwenden"
+   :wallet-invalid-address                "Ungültige Adresse: \n {{data}}"
+   :wallet-browse-photos                  "Fotos durchsuchen"
+   :validation-amount-invalid-number      "Menge ist keine gültige Zahl"
+   :validation-amount-is-too-precise      "Menge ist zu präzise. Die kleinste Einheit, die du senden kannst, ist 1 Wei (1x10^-18 ETH)"
+
+
+
+   ;; network settings
+   :new-network                           "Neues Netzwerk"
+   :add-network                           "Netzwerk hinzufügen"
+   :add-new-network                       "Neues Netzwerk hinzufügen"
+   :existing-networks                     "Existierende Netzwerke"
+   :add-json-file                         "JSON Datei hinzufügen"
+   :paste-json-as-text                    "JSON als Text einfügen"
+   :paste-json                            "JSON einfügen"
+   :specify-rpc-url                       "Spezifiziere eine RPC URL"
+   :edit-network-config                   "Netzwerkeinstellungen bearbeiten"
+   :connected                             "Verbunden"
+   :process-json                          "JSON verarbeiten"
+   :error-processing-json                 "Fehler beim Verarbeiten von JSON"
+   :rpc-url                               "RPC URL"
+   :remove-network                        "Netzwerk entfernen"
+   :network-settings                      "Netzwerkeinstellungen"
+   :edit-network-warning                  "Sei vorsichtig, das Bearbeiten der Netzwerkinformationen kann das Netzwerk für dich deaktivieren"
+   :connecting-requires-login             "Das Verbinden mit einem anderen Netzwerk erfordert eine Anmeldung"
+   :close-app-title                       "Warnung!"
+   :close-app-content                     "Die App wird gestoppt und geschlossen. Wenn du sie wieder öffnest, wird das ausgewählte Netzwerk verwendet"
+   :close-app-button                      "Bestätigen"})


Small clearing

Small clearing

--- src/export_server/utils/phantom.clj
+++ src/export_server/utils/phantom.clj
@@ -22,7 +22,6 @@
   (.add drivers driver))

 (defn setup-phantom []
-  ;(set-driver! (init-driver {:webdriver (PhantomJSDriver. (DesiredCapabilities.))}))
   (alter-var-root (var drivers)
                   (fn [_]
                     (doto (java.util.concurrent.ConcurrentLinkedQueue.)
@@ -49,17 +48,8 @@
         right-trim-str (clojure.string/replace left-trim-str #"\"$" "")]
     right-trim-str))

-(defn- get-script [script]
-  (str "document.body.innerHTML = '

';"
-       anychart-binary
-       script))
-
 (defn- exec-script-to-svg [d script exit-on-error options]
-  (let [;run-all
-        ; (try
-        ;   (execute-script d (get-script script) [(:container-id options) (:container-width options) (:container-height options)])
-        ;   (catch Exception e (str "Failed to execute Startup Script\n" (.getMessage e))))
-        startup
+  (let [startup
         (try
           (execute-script d "document.body.innerHTML = '

'", [(:container-id options) (:container-width options) (:container-height options)])
           (catch Exception e (str "Failed to execute Startup Script\n" (.getMessage e))))
@@ -80,7 +70,6 @@
                 (if (> (System/currentTimeMillis) (+ now 2000))
                   "error"
                   (do
-                    (prn "Waiting for svg...")
                     (Thread/sleep 10)
                     (recur))))))
           (catch Exception e (str "Failed to wait for SVG\n" (.getMessage e))))


moving neo4j-clj to gorillalabs.

moving neo4j-clj to gorillalabs.

--- components/neo4j/project.clj
+++ components/neo4j/project.clj
@@ -5,6 +5,6 @@

             :dependencies [[gorillalabs.tesla/core :version]
                            [com.taoensso/timbre "4.6.0"]
-                           [neo4j-clj "0.3.1-SNAPSHOT"]
+                           [gorillalabs/neo4j-clj "0.3.1-SNAPSHOT"]
                            ])


forgot there were actual tests for resolve

--- src/test/shadow/build/npm_test.clj
+++ src/test/shadow/build/npm_test.clj
@@ -3,6 +3,7 @@
             [clojure.pprint :refer (pprint)]
             [clojure.java.io :as io]
             [shadow.build.npm :as npm]
+            [shadow.build.resolve :refer (find-npm-resource)]
             [shadow.cljs.devtools.server.npm-deps :as npm-deps]
             [shadow.cljs.util :as util]))

@@ -16,7 +17,7 @@

 (deftest test-missing-package-returns-nil
   (with-npm [x {}]
-    (let [rc (npm/find-resource x nil "i-dont-exist" {})]
+    (let [rc (find-npm-resource x nil "i-dont-exist" {})]
       (is (nil? rc))
       )))

@@ -35,7 +36,7 @@
 (deftest test-browser-override
   (with-npm [x {}]
     (let [{:keys [resource-name ns file package-name] :as rc}
-          (npm/find-resource x nil "pkg-a" {})]
+          (find-npm-resource x nil "pkg-a" {})]

       ;; has browser override for index -> index-browser
       (is rc)
@@ -54,7 +55,7 @@
 (deftest test-resolve-to-global
   (with-npm [x {}]
     (let [{:keys [ns type requires source] :as rc}
-          (npm/find-resource x nil "react"
+          (find-npm-resource x nil "react"
             {:target :browser
              :resolve
              {"react" {:target :global
@@ -70,7 +71,7 @@
 (deftest test-resolve-to-file
   (with-npm [x {}]
     (let [{:keys [ns resource-name] :as rc}
-          (npm/find-resource x nil "react"
+          (find-npm-resource x nil "react"
             {:mode :release
              :resolve
              {"react" {:target :file
@@ -84,7 +85,7 @@
 (deftest test-resolve-to-other
   (with-npm [x {}]
     (let [{:keys [ns resource-name] :as rc}
-          (npm/find-resource x nil "react"
+          (find-npm-resource x nil "react"
             {:target :browser
              :resolve
              {"react" {:target :npm
@@ -100,7 +101,7 @@
 (deftest test-relative-file
   (with-npm [x {}]
     (let [{:keys [ns resource-name] :as rc}
-          (npm/find-resource x
+          (find-npm-resource x
             (-> (io/file ".")
                 (.getCanonicalFile))
             "./src/test/foo" {})]
@@ -129,10 +130,10 @@
     (let [ctx {}

           {:keys [file] :as rc1}
-          (npm/find-resource x nil "pkg-a/nested/thing" ctx)
+          (find-npm-resource x nil "pkg-a/nested/thing" ctx)

           {:keys [ns resource-name] :as rc2}
-          (npm/find-resource x file ".." ctx)]
+          (find-npm-resource x file ".." ctx)]

       (is rc1)
       (is rc2)
@@ -147,7 +148,7 @@
     (let [ctx {}

           {:keys [resource-name] :as rc1}
-          (npm/find-resource x nil "file-over-dir/foo" ctx)]
+          (find-npm-resource x nil "file-over-dir/foo" ctx)]

       (is rc1)
       (is (string? resource-name))
@@ -160,7 +161,7 @@
     (let [ctx {}

           {:keys [resource-name] :as rc1}
-          (npm/find-resource x nil "entry-dir/foo" ctx)]
+          (find-npm-resource x nil "entry-dir/foo" ctx)]

       (is rc1)
       (is (string? resource-name))


Add link and cache warning to account migration success page. Fixes #85.

--- src/clj/clojuredocs/pages/user.clj
+++ src/clj/clojuredocs/pages/user.clj
@@ -1,5 +1,6 @@
 (ns clojuredocs.pages.user
   (:require [clojuredocs.util :as util]
+            [clojuredocs.config :as config]
             [clojuredocs.pages.common :as common]
             [clojuredocs.mail :as mail]
             [somnium.congomongo :as mon]
@@ -138,6 +139,8 @@
                       :where {:author.login login
                               :author.account-source "clojuredocs"})]

+            ;; Wheeeeee
+
             (doseq [e examples]
               (mon/update! :examples
                 {:_id (:_id e)}
@@ -195,8 +198,13 @@
                   (count example-edits)
                   " examples edited by you, "
                   (count example-histories)
-                  " example histories "
+                  " example histories, "
                   (count notes)
                   " notes, and "
                   (count sas)
-                  " see alsos."]]]})))))))
+                  " see alsos."]
+                 [:p
+                  "Your new user URL is "
+                  [:a {:href (config/url "/u/" (:login user))}
+                   (config/url "/u/" (:login user))]
+                  ". Please note that the "Top Contributors" section on the home page is cached, and may show your old user URL for the next few minutes."]]]})))))))


added more general version of pixel-generator.

--- src/clj/forma/hadoop/predicate.clj
+++ src/clj/forma/hadoop/predicate.clj
@@ -21,6 +21,29 @@

 ;; ### Generators

+;; TODO: Cause pixel-generator to be a special case of this.
+(defn lazy-generator
+  "Returns a cascalog generator on the supplied lazy
+  sequence. `lazy-generator` serializes each item in the lazy sequence
+  into a sequencefile located at the supplied temporary directory, and
+  returns a tap into its guts.
+
+I recommend wrapping queries that use this tap with
+`cascalog.io/with-fs-tmp`; for example,
+
+    (with-fs-tmp [_ tmp-dir]
+      (let [lazy-tap (pixel-generator tmp-dir lazy-seq)]
+      (?<- (stdout)
+           [?field1 ?field2 ... etc]
+           (lazy-tap ?field1 ?field2)
+           ...)))"
+  [tmp-path lazy-seq]
+  (let [tap (hfs-seqfile tmp-path)]
+    (with-open [collector (.openForWrite tap (JobConf.))]
+      (doseq [item lazy-seq]
+        (.add collector (Util/coerceToTuple item))))
+    tap))
+
 (defn pixel-generator
   "Returns a cascalog generator that produces every pixel combination
   for the supplied sequence of tiles, given the supplied
@@ -31,8 +54,8 @@
 I recommend wrapping queries that use this tap with
 `cascalog.io/with-fs-tmp`; for example,

-    (with-fs-tmp [fs tmp-dir]
-      (let [pix-tap (pixel-generator res tmp-dir tileseq)]
+    (with-fs-tmp [_ tmp-dir]
+      (let [pix-tap (pixel-generator tmp-dir res tileseq)]
       (?<- (stdout)
            [?mod-h ?mod-v ... etc]
            (pix-tap ?mod-h ?mod-v ?sample ?line)


sliced passport initial implementation

sliced passport initial implementation

--- src/clj/salava/extra/spaces/db.clj
+++ src/clj/salava/extra/spaces/db.clj
@@ -1,4 +1,4 @@
-(ns salava.extra.application.db
+(ns salava.extra.spaces.db
  (:require [yesql.core :refer [defqueries]]
            [salava.core.util :as u]
            [clojure.tools.logging :as log]


allow account options to be filtered by type

--- src/clj_money/web/money_shared.clj
+++ src/clj_money/web/money_shared.clj
@@ -17,6 +17,7 @@
   ([entity-id options]
    (cond->> entity-id
      true (accounts/select-by-entity-id (env :db))
+     (contains? options :types) (filter #(contains? (:types options) (:type %)))
      true (sort-by :name)
      true (map #(select-keys % [:id :name]))
      true (map #(rename-keys % {:id :value


fix modal structure

fix modal structure

--- src/cljs/salava/core/ui/modal.cljs
+++ src/cljs/salava/core/ui/modal.cljs
@@ -17,27 +17,25 @@
 (defn set-new-view [route params]
   (reset! views (conj @views [((get-in (modal-navi) route) params)])))

-(defn modal-content []
+(defn modal-content []
   [:div {:id "badge-content"}
+   [:div.modal-header
+    [:button {:type         "button"
+              :class        "close"
+              :data-dismiss "modal"
+              :aria-label   "OK"}
+     [:span {:aria-hidden             "true"
+             :dangerouslySetInnerHTML {:__html "×"}}]]
+    (if (< 1 (count @views))
+      [:div {:class "pull-left"}
+       [:button {:type  "button"
+                 :class "close"
+                 :aria-label "OK"
+                 :on-click #(do
+                              (reset! views (pop @views))
+                              (.preventDefault %))}
+        [:span {:class "back-arrow" :aria-hidden "true"}]]])]
    [:div.modal-body
-    [:div
-     [:div.col-md-12
-      (if (< 1 (count @views))
-        [:div {:class "pull-left"}
-         [:button {:type  "button"
-                   :class "close"
-                   :aria-label "OK"
-                   :on-click #(do
-                                (reset! views (pop @views))
-                                (.preventDefault %))}
-          [:i {:class "fa fa-arrow-circle-left fa-lg" :aria-hidden "true"}]]])
-      [:div {:class "text-right"}
-       [:button {:type         "button"
-                 :class        "close"
-                 :data-dismiss "modal"
-                 :aria-label   "OK"}
-        [:span {:aria-hidden             "true"
-                :dangerouslySetInnerHTML {:__html "×"}}]]]]]
     [:div (last @views)]]
    [:div.modal-footer ]])


Update words.clj

Update words.clj

--- src/iyye/subcon/knowledge/words.clj
+++ src/iyye/subcon/knowledge/words.clj
@@ -14,121 +14,82 @@
 ; You should have received a copy of the GNU Affero General Public License
 ; along with this program.  If not, see <http://www.gnu.org/licenses/>.

-(ns iyye.subcon.knowledge.words
-  (:require
-    [clojure.tools.logging :as log]
-    [iyye.bios.ioframes :as ioframes]
-    [iyye.bios.persistence :as persistence]
-    ;[iyye.subcon.knowledge.relation :as relation]
-    ))
+(ns iyye.bios.words
+   (:require [clojure.string :as str]
+             [iyye.bios.ioframes :as ioframes]
+             [iyye.bios.task :as task]
+             [iyye.bios.noun-words :as nouns]))

-(def relations-words (ref []))
-(def types-words (ref []))
-(def instances-words (ref []))
-(def adjective-words (ref []))
-(def action-words (ref []))
+(defrecord action-word [word function async-function-task])

-(defrecord Iyye_Predicate [AccordingTo When Time Prob])
+(defn list-func [IO arg]
+  (let [noun-names (pr-str (map :word @nouns/noun-words-list))]
+ (ioframes/process-output IO (str "list of nouns: " noun-names))))

-(defrecord Iyye_Atom [Name Uname predicate])
+(defn getter-func [IO arg]
+  (let [name (first arg)]
+    (let [matches
+          (for [noun @nouns/noun-words-list :when (= (:word noun) name)]
+            noun)]
+      (case (count matches)
+        0 (ioframes/process-output IO (str "failed to parse: no matching getter for " name))
+        1 (let [action (first matches)
+                result ((:getter-function action))]
+          (ioframes/process-output IO (str "The value of " name " is " result)))
+        (ioframes/process-output IO (str "failed to parse: too many matched getters to " name))))))

-(defn create-iyye-atom [name according when words-list]
-  (let [Time (persistence/current-time-to-string)
-        uname (str name (count words-list))
-        atom (->Iyye_Atom name uname (->Iyye_Predicate according when Time 1.0))]
-    atom))
+(defn setter-func [IO arg]
+  (if (not= 2 (count arg))
+    (ioframes/process-output IO (str "Can't set, need 2 arguments")))
+  (let [name (first arg)
+        value (second arg)]
+    (let [matches
+          (for [noun @nouns/noun-words-list :when (= (:word noun) name)]
+            noun)]
+      (case (count matches)
+        0 (ioframes/process-output IO (str "failed to parse: no matching setter for " name))
+        1 (let [action (first matches)
+                func (:setter-function action)]
+            (if func
+              (ioframes/process-output IO (str "Set " name " to " value " " (func value)))
+              (ioframes/process-output IO (str "Can't set " name " to " value))))
+        (ioframes/process-output IO (str "failed to parse: too many matched setters to " name))))))

-(defrecord Iyye_Type [atom SubtypeOf Subtypes Predicates])
+(defn shutdown-func [IO arg]
+  (ioframes/process-output IO (str "Shutting down!"))
+  (task/shutdown))

-(defn create-iyye-type [Name AccordingTo When SubtypeOf Subtypes]
-  (let [type-atom (create-iyye-atom Name AccordingTo When types-words)
-        type (->Iyye_Type type-atom SubtypeOf Subtypes [])]
-    type))
+(defn pause-func [IO arg]
+  (task/pause)
+  (ioframes/process-output IO (str "Paused")))

-(defn load-iyye-atom-from-db [uname]
-  )
+(defn resume-func [IO arg]
+  (task/resume)
+  (ioframes/process-output IO (str "Resumed")))

-(defn load-iyye-type-from-db [name]
-  )
+(defn help-func [IO arg]
+  (ioframes/process-output IO (str "Available actions: list, get, set, shutdown, pause, resume, help")))

-;(dosync (alter types-words conj type))
-;(persistence/write-noun-to-db (into {} type))
+(def list-action (action-word. "list" list-func nil))
+(def get-action (action-word. "get" getter-func nil))
+(def set-action (action-word. "set" setter-func nil))
+(def shutdown-action (action-word. "shutdown" shutdown-func nil))
+(def pause-action (action-word. "pause" pause-func nil))
+(def resume-action (action-word. "resume" resume-func nil))
+(def help-action (action-word. "help" help-func nil))

-(defrecord Iyye_Relation [atom Reason Types Function])
-
-(defn create-iyye-relation [Name AccordingTo Reason When Types Function]
-  (let [action-atom (create-iyye-atom Name AccordingTo When @relations-words)
-        relation (->Iyye_Relation action-atom Reason Types Function)]
-    relation))
-
-(defrecord Iyye_Instance [atom type])
-
-(defn create-iyye-instance [values])
-
-;(dosync (alter relations-words conj relation))
-;(persistence/write-action-to-db (conj (into {} (:atom 8action)) (dissoc (into {} action) :atom)))
-;
-; (defn write-to-db [atom]
-;  (persistence/write-knowledge-to-db (conj (into {} (:atom action)) (dissoc (into {} action) :atom))))
-
-;(defn ^{:source "(+ 1 a)"} aaa [a] (+ 1 a))
-;(defmacro getsrc [func] `(:source (meta (var ~func))))
-
-(defn iyye_is_type_function [p1 p2]
-  (let [p2-type (load-iyye-type-from-db p2)
-        newtype (if p2-type p2-type (create-iyye-type p2 :IYE :ALWAYS p1 []))])
-
-  )
-
-(defn iyye_consists_function [p1 p2]
-  (let [])
-  )
-
-(defn iyye_instance_function [p1 name]
-  (let [])
-  )
-
-(def iyye_is_type (ref 0))
-(def iyye_consists_type (ref 0))
-(def iyye_create_instance (ref 0))
+; FIXME to add runtime configuring
+(def action-words (ref (list get-action set-action shutdown-action pause-action resume-action help-action list-action)))

 (defn action [cmd params IO]
   (let [actions
-        (for [action @action-words :when (= (:Name action) cmd)]
-          action)]
+        (for [action @action-words :when (= (:word action) cmd)]
+            action)]
     (case (count actions)
       0 (ioframes/process-output IO (str "failed to parse: no matching action to " cmd))
       1 (let [action (first actions)]
-          (if (compare params (:Types action))
-            ((:Function action) params)
-            (ioframes/process-output IO (str "failed to parse: types mismatch " cmd ": " action ":" params))))
+          (if (:async-function-task action)
+            (task/run-off-task (:async-function-task action) params)
+            ((:function action) IO params)))
       (ioframes/process-output IO (str "failed to parse: too many matched action to " cmd ": " actions)))))

-(defn- init-builtins-kb []
-  (let [t_is (create-iyye-relation "is" :IYE :AXIOM :ALWAYS [] iyye_is_type_function)
-        consistsof (create-iyye-relation "consists" :IYE :AXIOM :ALWAYS [] iyye_consists_function)
-        instof (create-iyye-relation "instance of" :IYE :AXIOM :ALWAYS [] iyye_instance_function)]
-    (dosync (ref-set iyye_is_type t_is))
-    (dosync (ref-set iyye_consists_type consistsof))
-    (dosync (ref-set iyye_create_instance instof))
-    ; (dosync (alter noun-words conj iyye_concept))
-    ;(dorun (map #(do ( persistence/write-fact-to-db (into {} %))) @action-words))
-    ))
-
-(defn- init-db-kb []
-  (let []
-    (dosync (alter relations-words #(apply conj %1 %2) (persistence/read-knowledge-from-db "relations" {:When :ALWAYS})))
-    (dosync (alter types-words #(apply conj %1 %2) (persistence/read-knowledge-from-db "types" {:When :ALWAYS})))
-    ))
-
-(defn load-init-kb []
-  (init-builtins-kb)
-  (init-db-kb)
-
-  )
-
-(defn init-kb []
-  (init-builtins-kb)
-  )
-
-; (apply str (rest (str (:When {:When :ALWAYS}))))


Type hinting and some refactoring

Type hinting and some refactoring

--- src/wireframes/renderer/bitmap.clj
+++ src/wireframes/renderer/bitmap.clj
@@ -13,67 +13,57 @@
       (let [brightness (Math/max 5 (Math/min brightness 250))]
         (Color. brightness brightness brightness)))))

-(defn- draw-dot [^Graphics2D g2d [^double x ^double y] size]
-  (.fill g2d (Ellipse2D$Double. (- x (/ size 2)) (- y (/ size 2)) size size)))
+(defn transparent? [^Color color]
+  (and color (zero? (.getAlpha color))))

-(defn- add-line [^GeneralPath path [^double ax ^double ay] [^double bx ^double by]]
-  (doto path
-    (.moveTo ax ay)
-    (.lineTo bx by))
-  path)
+(defn solid? [^Color color]
+  (and color (pos? (.getAlpha color))))

-(defn- create-polygon [^GeneralPath path [[^double ax ^double ay] & more]]
-  (doto path
-    (.reset)
-    (.moveTo ax ay))
-  (doseq [[^double bx ^double by] more]
-    (.lineTo path bx by))
-  (.closePath path)
-  path)
+(defn walk-polygon [^GeneralPath path points-2d polygon]
+  (let [[^double ax ^double ay] (get points-2d (first polygon))]
+    (doto path
+      (.reset)
+      (.moveTo ax ay))
+    (loop [ps (next polygon)]
+      (when-let [[^double bx ^double by] (get points-2d (first ps))]
+        (.lineTo path bx by)
+        (recur (next ps))))
+    (.closePath path)))

-(defn draw-wireframe [{:keys [focal-length transform shape]} ^Graphics2D g2d]
-  (let [path (GeneralPath.)
-        points-3d (get-3d-points transform shape)
-        points-2d (get-2d-points focal-length points-3d)]
+(defn wireframe-draw-fn [^Graphics2D g2d points-2d ^Color fill-color ^Color edge-color]
+  (let [path (GeneralPath.)]
+    (fn [polygon]
+      (walk-polygon path points-2d polygon)
+      (doto g2d
+        (.setColor fill-color)
+        (.fill path)
+        (.setColor edge-color)
+        (.draw path)))))

-    ;(.setColor g2d Color/RED)
-    ;(doseq [[idx1 idx2] (:lines shape)]
-    ;  (draw-dot g2d (points-2d idx1) 0.008))
-
-    ;(.setColor g2d Color/GREEN)
-    ;(doseq [[idx1 idx2 idx3] (:polygons shape)]
-    ;  (add-line path (points-2d idx1) (points-2d idx2))
-    ;  (add-line path (points-2d idx1) (points-2d idx3))
-    ;  (add-line path (points-2d idx2) (points-2d idx3))
-    ;  )
-    ;(.draw g2d path)
-    ;(.reset path)
-
-    (.setColor g2d Color/BLACK)
-    (doseq [line (:lines shape)]
-      (apply add-line path (map points-2d line)))
-    (.draw g2d path)))
+(defn shader-draw-fn [^Graphics2D g2d points-2d shader]
+  (let [path (GeneralPath.)]
+    (fn [polygon]
+      (walk-polygon path points-2d polygon)
+      (doto g2d
+        (.setColor (shader polygon))
+        (.fill path)
+        (.draw path)))))

 (defn draw-solid [{:keys [focal-length transform shape fill-color]} ^Graphics2D g2d]
-  (let [path (GeneralPath.)
+  (let [
         points-3d (get-3d-points transform shape)
         points-2d (get-2d-points focal-length points-3d)
-        shader    (shader points-3d create-color)
         polygons  (cond
-                    (and fill-color (zero? (.getAlpha fill-color))) (:polygons shape)
-                    (and fill-color) (sort-by (priority-fill points-3d) (:polygons shape))
-                    :else (sort-by (priority-fill points-3d) (t/reduce-polygons (:polygons shape))))]
-    (doseq [polygon polygons
-            :let [p (create-polygon path (map points-2d polygon))
-                  face-color (if fill-color fill-color (shader polygon))
-                  edge-color (if fill-color Color/BLACK face-color)]]
-        (doto g2d
-          (.setColor face-color)
-          (.fill p)
-          (.setColor edge-color)
-          (.draw p)))))
+                    (transparent? fill-color) (:polygons shape)
+                    (solid? fill-color)       (sort-by (priority-fill points-3d) (:polygons shape))
+                    :else                     (sort-by (priority-fill points-3d) (t/reduce-polygons (:polygons shape))))
+        draw-fn   (if (or (transparent? fill-color) (solid? fill-color))
+                    (wireframe-draw-fn g2d points-2d fill-color Color/BLACK)
+                    (shader-draw-fn g2d points-2d (shader points-3d create-color)))]
+    (doseq [polygon polygons]
+      (draw-fn polygon))))

-(defn create-image [w h]
+(defn ^BufferedImage create-image [w h]
   (if (GraphicsEnvironment/isHeadless)
     (BufferedImage. w h BufferedImage/TYPE_INT_ARGB)
     (.createCompatibleImage
@@ -82,23 +72,28 @@
            (GraphicsEnvironment/getLocalGraphicsEnvironment)))
        w h)))

+(defn ^Graphics2D create-graphics [^BufferedImage img]
+  (let [g2d (.createGraphics img)]
+    (doto g2d
+      (.setRenderingHint RenderingHints/KEY_STROKE_CONTROL RenderingHints/VALUE_STROKE_NORMALIZE)
+      (.setRenderingHint RenderingHints/KEY_ANTIALIASING RenderingHints/VALUE_ANTIALIAS_ON)
+      (.setRenderingHint RenderingHints/KEY_RENDERING RenderingHints/VALUE_RENDER_QUALITY))
+    g2d))
+
 (defn ->img [draw-fn [w h]]
   (let [img (create-image w h)
-        g2d (.createGraphics img)
-        scale (min (quot w 2) (quot h 2))]
+        g2d (create-graphics img)
+        scale (double (min (/ w 2) (/ h 2)))]
     (doto g2d
       (.setBackground Color/WHITE)
       (.clearRect 0 0 w h)
       (.setColor Color/BLACK)
-      (.translate (quot w 2) (quot h 2))
+      (.translate (double (/ w 2)) (double (/ h 2)))
       (.scale scale scale)
-      (.setStroke (BasicStroke. (/ 1.0 (quot w 2))))
-      (.setRenderingHint RenderingHints/KEY_STROKE_CONTROL RenderingHints/VALUE_STROKE_NORMALIZE)
-      (.setRenderingHint RenderingHints/KEY_ANTIALIASING RenderingHints/VALUE_ANTIALIAS_ON)
-      (.setRenderingHint RenderingHints/KEY_RENDERING RenderingHints/VALUE_RENDER_QUALITY))
+      (.setStroke (BasicStroke. (/ 0.5 w))))
     (draw-fn g2d)
     (.dispose g2d)
     img))

-(defn write-png [image filename]
+(defn write-png [^BufferedImage image filename]
   (ImageIO/write image "png" (clojure.java.io/file filename)))


Minor cleanup

Minor cleanup

--- src/main/clojure/clj_print/core.clj
+++ src/main/clojure/clj_print/core.clj
@@ -96,8 +96,9 @@
     :url (:autosense flavors/urls)
     nil))

-(defn setify
-  "Takes a Clojure set and returns an Attribute"
+(defn- setify
+  "Takes a Clojure set and returns an AttributeSet implementation
+   based on bound."
   [^clojure.lang.IPersistentSet s bound]
   (if (seq s)
     (let [el (first s)
@@ -111,17 +112,26 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Job ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 (defprotocol IPrintable
-  (submit [this & {:keys [s-attrs]}] "Submits the IPrintable for printing, with optional service attributes."))
+  (submit
+    [this & {:keys [s-attrs]}]
+    "Submits the IPrintable for printing, with optional service attributes."))

 ;; TODO: Only allow maps
 (defrecord JobMap [doc printer job]
   IPrintable
   (submit [this & {:keys [s-attrs]}]
-    (let [{:keys [attrs obj]} job
-          sdoc (make-doc (:source doc) (:flavor doc) (:attrs doc))]
+    (let [{:keys [attrs ^DocPrintJob obj]} job
+          sdoc (make-doc (:source doc)
+                         (:flavor doc)
+                         (:attrs doc))] ;; TODO: bleh destructure this
       (.. obj (print @sdoc s-attrs)))))

-;; TODO: Should printer be optional?
+;; TODO: Create auxiliary fns like job-params/doc-params?
+
+;; TODO: Should printer be optional? If I create these, I can use rest
+;; params and avoid instantiating PersistentHashSets (but then I can't
+;; use literals, hmm)
+
 (defn make-jobmap [doc & {:keys [printer attrs]
                           :or {printer (printer)
                                attrs (setify #{MediaTray/MAIN} :job)}}]
@@ -152,31 +162,6 @@
                    nil)]
     (delay (SimpleDoc. resource flavor attrs))))

-;; TODO: Win32PrintService.java will close the streams when it's done,
-;; check IPPrintService.java
-;; (defn- print-action
-;;   "Calls print on the job, but considers the doc-source-type."
-;;   [j-map]
-;;   (let [{:keys [^DocPrintJob job
-;;                 ^String doc-source
-;;                 doc-flavor
-;;                 doc-attrs
-;;                 job-attrs]} j-map]
-;;     (condp = (doc-source-type doc-source)
-;;       :file (with-open [fis (FileInputStream. doc-source)] ;; Close anyways
-;;               (.. job (print (make-doc fis doc-flavor doc-attrs) job-attrs)))
-;;       :url (.. job (print (make-doc (URL. doc-source) doc-flavor doc-attrs) job-attrs))
-;;       nil (throw (RuntimeException. "Unrecognized document source")))))
-
-;; (defn submit
-;;   "Requests a dead tree representation of the document specified
-;;    in the job map (sends the print job to the printer)."
-;;   [j-map]
-;;   (let [action (delay (print-action j-map))]
-;;     (try
-;;       @action
-;;       (catch PrintException pe (.. pe printStackTrace)))))
-
 ;; (defn -main [& args]
 ;;   (if (seq args)
 ;;     (doseq [v args]


display negative durations as 00:00

display negative durations as 00:00

--- frontend/datetime.cljs
+++ frontend/datetime.cljs
@@ -1,5 +1,6 @@
 (ns frontend.datetime
-  (:require [goog.string :as g-string]
+  (:require [frontend.utils :as utils :include-macros true]
+            [goog.string :as g-string]
             goog.string.format
             [goog.i18n.DateTimeFormat.Format :as date-formats]))

@@ -125,11 +126,14 @@
       (str count " "  (:unit interval) (when-not (= 1 count) "s")))))

 (defn as-duration [duration]
-  (let [seconds (js/Math.floor (/ duration 1000))
-        minutes (js/Math.floor (/ seconds 60))
-        hours (js/Math.floor (/ minutes 60))
-        display-seconds (g-string/format "%02d" (mod seconds 60))
-        display-minutes (g-string/format "%02d" (mod minutes 60))]
-    (if (pos? hours)
-      (g-string/format "%s:%s:%s" hours display-minutes display-seconds)
-      (g-string/format "%s:%s" display-minutes display-seconds))))
+  (if (neg? duration)
+    (do (utils/mwarn "got negative duration" duration "returning 00:00")
+        "00:00")
+    (let [seconds (js/Math.floor (/ duration 1000))
+          minutes (js/Math.floor (/ seconds 60))
+          hours (js/Math.floor (/ minutes 60))
+          display-seconds (g-string/format "%02d" (mod seconds 60))
+          display-minutes (g-string/format "%02d" (mod minutes 60))]
+      (if (pos? hours)
+        (g-string/format "%s:%s:%s" hours display-minutes display-seconds)
+        (g-string/format "%s:%s" display-minutes display-seconds)))))


No more reflection! Also abandoned MultiJobSpec in favor of a lazy sequence of JobSpecs

--- src/main/clojure/clj_print/core.clj
+++ src/main/clojure/clj_print/core.clj
@@ -106,10 +106,18 @@
   [^clojure.lang.IPersistentSet s bound]
   (if (seq s)
     (condp = bound
-      :service (HashPrintServiceAttributeSet. (into-array PrintServiceAttribute s))
-      :job (HashPrintJobAttributeSet. (into-array PrintJobAttribute s))
-      :doc (HashDocAttributeSet. (into-array DocAttribute s))
-      :request (HashPrintRequestAttributeSet. (into-array PrintRequestAttribute s))
+      :service (HashPrintServiceAttributeSet.
+                #^"[Ljavax.print.attribute.PrintServiceAttribute;"
+                (into-array PrintServiceAttribute s))
+      :job (HashPrintJobAttributeSet.
+            #^"[Ljavax.print.attribute.PrintJobAttribute;"
+            (into-array PrintJobAttribute s))
+      :doc (HashDocAttributeSet.
+            #^"[Ljavax.print.attribute.DocAttribute;"
+            (into-array DocAttribute s))
+      :request (HashPrintRequestAttributeSet.
+                #^"[Ljavax.print.attribute.PrintRequestAttribute;"
+                (into-array PrintRequestAttribute s))
       nil)))

 (defn- valid-attrs?
@@ -150,65 +158,64 @@

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Job ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

-;;  A JobSpec might look something like this:
-(comment {:doc {:source "/path/to/doc.pdf"
-                :flavor (:autosense flavors/input-streams)
-                :attrs #{Chromaticity/MONOCHROME
-                         PrintQuality/HIGH
-                         OrientationRequested/PORTRAIT}}
-          :printer (printer "HP_Color_LaserJet_CP3505")
-          :attrs #{(Copies. 5) MediaTray/MAIN}
-          :listener (listeners/basic-listener)})
-
-;; Or
-
-(comment {:docs [{:source "/path/to/doc1.pdf"
-                  :flavor (:autosense flavors/input-streams)
-                  :attrs #{Chromaticity/MONOCHROME}}
-                 {:source "http://somesite.com/doc2.pdf"
-                  :flavor (:autosense flavors/urls)
-                  :attrs #{Chromaticity/COLOR}}]
-          :printer (printer :default)
-          :attrs #{MediaTray/MAIN}
-          :listener (listeners/basic-listener)})
-
 (defprotocol IJobSpec
-  (submit [this])
-  (add-listener [this listener-fn]))
-
-;; TODO: Handle exception scenarios
+  "Protocol for print job data structures"
+  (submit! [this])
+  (add-listener! [this listener-fn]))
+
 (defrecord JobSpec [doc printer job attrs]
   IJobSpec
-  (submit [this]
+  (submit! [this]
     (if-let [{listener-fn :listener-fn} this]
-      (add-listener this listener-fn))
+      ;; Listeners are not added until right before submission
+      (add-listener! this listener-fn))
     (let [{{doc-obj :obj} :doc} this
           {:keys [^DocPrintJob job attrs]} this
           attr-set (make-set attrs :request)]
       (.. job (print doc-obj attr-set))))
-  (add-listener [this listener-fn]
+  (add-listener! [this listener-fn]
     (let [{:keys [^DocPrintJob job listener-fn]} this
           listener (listener-fn)]
       (doto job (.addPrintJobListener listener)))))

-(defrecord MultiJobSpec [docs printer jobs attrs]
-  IJobSpec
-  (submit [this]
-    (if-let [{listener-fn :listener-fn} this]
-      (add-listener this listener-fn))
-    (let [{:keys [docs jobs]} this
-          doc-objs (map :obj docs)]
-      (doall
-       (map (fn [^DocPrintJob j d]
-              (.. j (print @d (make-set attrs :request)))) jobs doc-objs))))
-  (add-listener [this listener-fn]
-    (let [{:keys [jobs listener-fn]} this]
-      (doseq [^DocPrintJob j jobs]
-        (.. j (addPrintJobListener (listener-fn)))))))
-
-;; TODO: SEE http://oobaloo.co.uk/clojure-from-callbacks-to-sequences!!!
+;;  A JobSpec might look something like this:
+;; {:doc {:source "/path/to/doc.pdf"
+;;        :flavor (:autosense flavors/input-streams)
+;;        :attrs #{Chromaticity/MONOCHROME
+;;                 PrintQuality/HIGH
+;;                 OrientationRequested/PORTRAIT}}
+;;  :printer (printer "HP_Color_LaserJet_CP3505")
+;;  :attrs #{(Copies. 5) MediaTray/MAIN}
+;;  :listener (listeners/basic-listener)}
+
+;; Or
+;; {:docs [{:source "/path/to/doc1.pdf"
+;;          :flavor (:autosense flavors/input-streams)
+;;          :attrs #{Chromaticity/MONOCHROME}}
+;;         {:source "http://somesite.com/doc2.pdf"
+;;          :flavor (:autosense flavors/urls)
+;;          :attrs #{Chromaticity/COLOR}}]
+;;  :printer (printer :default)
+;;  :attrs #{MediaTray/MAIN}
+;;  :listener (listeners/basic-listener)}
+
 (defmulti make-job
-  "Dispatch on which key is present in the spec map."
+  "Returns a JobSpec map that is the result of
+   assoc'ing required values to it. The values are:
+
+   1. A SimpleDoc object (wrapped in a Delay) made from
+   the map keyed at :doc.
+   2. A DocPrintJob object that is retrieved from the
+   PrintService.
+
+   The following defaults are also assoc'd to the job-spec
+   if no values are supplied for them:
+
+   1. The default system printer.
+   2. An attribute set with the single attribute MediaTray/MAIN.
+   3. A basic PrintJobListener that prints any events that occur
+   on the DocPrintJob."
+  {:since "0.0.1"}
   (fn [spec] (apply (some-fn #{:doc} #{:docs}) (keys spec))))

 (defmethod make-job :doc [spec]
@@ -223,67 +230,39 @@
         (-> spec add-doc add-job map->JobSpec)))))

 (defmethod make-job :docs [spec]
-  (let [{:keys [^PrintService printer
-                ^PrintJobListener listener
-                docs attrs]} spec]
-    (if (and (every? (fn [d] (valid-attrs? d :doc)) (map :attrs docs))
-             (valid-attrs? attrs :job))
-      (letfn [(add-doc [doc-map]
-                (assoc-in doc-map [:obj] (delay (make-doc doc-map))))
-              (add-docs [spec]
-                (update-in spec [:docs] (fn [doc-list] (map add-doc  doc-list))))
-              (add-jobs [spec]
-                (assoc-in spec [:jobs] (for [doc docs] (.. printer createPrintJob))))]
-        (-> spec add-docs add-jobs map->MultiJobSpec)))))
-
-;; (defn make-job
-;;   "Returns a JobSpec map that is the result of
-;;    assoc'ing required values to it. The values are:
-
-;;    1. A SimpleDoc object (wrapped in a Delay) made from
-;;    the map keyed at :doc.
-;;    2. A DocPrintJob object that is retrieved from the
-;;    PrintService.
-
-;;    The following defaults are also assoc'd to the job-spec
-;;    if no values are supplied for them:
-
-;;    1. The default system printer.
-;;    2. An attribute set with the single attribute MediaTray/MAIN.
-;;    3. A basic PrintJobListener that prints any events that occur
-;;    on the DocPrintJob."
-;;   {:since "0.0.1"}
-;;   [spec]
-;;   (cond
-;;    (:doc spec) (let [{{doc-attrs :attrs} :doc} spec
-;;                      {:keys [doc ^PrintService printer attrs ^PrintJobtListener listener]
-;;                       :or {printer (printer :default)
-;;                            attrs #{MediaTray/MAIN}}} spec
-;;                            maybe-listen #(if listener (add-listener % listener) %)]
-;;                  (if (and (valid-attrs? doc-attrs :doc)
-;;                           (valid-attrs? attrs :job))
-;;                    (-> {:doc (assoc doc :obj (make-doc doc))
-;;                         :printer printer
-;;                         :attrs attrs
-;;                         :job (.. printer createPrintJob)}
-;;                        maybe-listen)))
-;;    (:docs spec) (let [{docs :docs} spec
-;;                      {:keys [doc ^PrintService printer attrs ^PrintJobtListener listener]
-;;                       :or {printer (printer :default)
-;;                            attrs #{MediaTray/MAIN}}} spec
-;;                            maybe-listen #(if listener (add-listener % listener) %)]
-;;                   (println "In :docs")
-;;                   (if (and (every? #(valid-attrs? (:attrs %) :doc) docs)
-;;                            (valid-attrs? attrs :job))
-;;                    (-> {:docs (map #(assoc % :obj (make-doc %)) docs)
-;;                         :printer printer
-;;                         :attrs attrs
-;;                         :job (.. printer createPrintJob)}
-;;                        maybe-listen)))
-;;    :else nil))
-
-(defn -main [& args]
+  (let [{docs :docs} spec]
+    (for [doc docs]
+      (-> spec (dissoc :docs) (assoc :doc doc) make-job))))
+
+;; Old method of encapsulating a 'MultiJobSpec', most
+;; values in a JobSpec will be Singleton/Enum instances
+;; anyways, so structural sharing may not be necessary,
+;; though I'll throw this in here anyways:
+;;
+;; TODO: Analyze memory consumption in JVisualVM for:
+;; 1. maps vs records being used for job specs in general
+;; 2. Using MultiJobSpec vs just using
+;;
+;; (defmethod make-job :docs [spec]
+;;   (let [{:keys [^PrintService printer
+;;                 ^PrintJobListener listener
+;;                 docs attrs]} spec]
+;;     (if (and (every? (fn [d] (valid-attrs? d :doc)) (map :attrs docs))
+;;              (valid-attrs? attrs :job))
+;;       (letfn [(add-doc [doc-map]
+;;                 (assoc-in doc-map [:obj] (delay (make-doc doc-map))))
+;;               (add-docs [spec]
+;;                 (update-in spec [:docs] (fn [doc-list] (map add-doc  doc-list))))
+;;               (add-jobs [spec]
+;;                 (assoc-in spec [:jobs] (for [doc docs] (.. printer createPrintJob))))]
+;;         (-> spec add-docs add-jobs map->MultiJobSpec)))))
+
+(defn -main
+  "Main method, expects each value in args to be the string
+   representation of a clojure map to be read by the reader."
+  {:since "0.0.1"}
+  [& args]
   (if (seq args)
     (doseq [v args]
       (let [spec (read-string v)]
-        (-> (make-job spec) submit)))))
+        (-> (make-job spec) submit!)))))


Removed an unnecessary atom used in the ini-to-map function in core (previously in PuppetDB utils.clj)

--- src/puppetlabs/kitchensink/core.clj
+++ src/puppetlabs/kitchensink/core.clj
@@ -378,6 +378,27 @@

 ;; ## Configuration files

+(def keywordize
+  "Normalize INI keys by ensuring they're lower-case and keywords"
+  (comp keyword string/lower-case))
+
+(defn fetch-int
+  "Fetch a key from the INI section and convert it
+   to an integer if it parses, otherwise return the string"
+  [section key]
+  (let [val (.fetch section key)]
+    (or (parse-int val)
+        val)))
+
+(defn create-section-map
+  "Given an INI section, create a clojure map of it's key/values"
+  [section]
+  (reduce (fn [acc [key _]]
+            (assoc acc
+              (keywordize key)
+              (fetch-int section key)))
+          {} section))
+
 (defn ini-to-map
   "Takes a .ini filename and returns a nested map of
   fully-interpolated values. Strings that look like integers are
@@ -385,20 +406,16 @@
   symbols."
   [filename]
   {:pre  [(or (string? filename)
-            (instance? java.io.File filename))]
+              (instance? java.io.File filename))]
    :post [(map? %)
           (every? keyword? (keys %))
           (every? map? (vals %))]}
-  (let [ini        (Ini. (reader filename))
-        m          (atom {})
-        keywordize #(keyword (string/lower-case %))]
-
-    (doseq [[name section] ini
-            [key _] section
-            :let [val (.fetch section key)
-                  val (or (parse-int val) val)]]
-      (swap! m assoc-in [(keywordize name) (keywordize key)] val))
-    @m))
+
+  (reduce (fn [acc [name section]]
+            (assoc acc
+              (keywordize name)
+              (create-section-map section)))
+          {} (Ini. (reader filename))))

 (defn inis-to-map
   "Takes a path and converts the pointed-at .ini files into a nested


add some try/catch on our slack api calls just to make sure they don't cause unwanted exceptions getting thrown up the call chain.

--- src/metabase/integrations/slack.clj
+++ src/metabase/integrations/slack.clj
@@ -20,9 +20,12 @@
     {:pre [(string? method)
            (map? params)]}
    (when token
-     (client/get (str slack-api-baseurl "/" method) {:query-params   (merge params {:token token})
-                                                     :conn-timeout   1000
-                                                     :socket-timeout 1000}))))
+     (try
+       (client/get (str slack-api-baseurl "/" method) {:query-params   (merge params {:token token})
+                                                       :conn-timeout   1000
+                                                       :socket-timeout 1000})
+       (catch Throwable t
+         (log/warn "Error making Slack API call:" (.getMessage t)))))))

 (defn slack-api-post
   "Generic function which calls a given method on the Slack api via HTTP POST."
@@ -32,9 +35,12 @@
    {:pre [(string? method)
           (map? params)]}
    (when token
-     (client/post (str slack-api-baseurl "/" method) {:form-params   (merge params {:token token})
-                                                      :conn-timeout   1000
-                                                      :socket-timeout 1000}))))
+     (try
+       (client/post (str slack-api-baseurl "/" method) {:form-params   (merge params {:token token})
+                                                        :conn-timeout   1000
+                                                        :socket-timeout 1000})
+       (catch Throwable t
+         (log/warn "Error making Slack API call:" (.getMessage t)))))))

 (defn- ^:private handle-api-response
   "Simple helper that checks that response is a HTTP 200 and deserializes the `:body` if so, otherwise logs an error"


Fix #58 in case of macros the wrong node selected

... for s-expression

--- src/refactor_nrepl/find_unbound.clj
+++ src/refactor_nrepl/find_unbound.clj
@@ -11,16 +11,17 @@
          (not-empty file)]}
   (throw-unless-clj-file file)
   (let [ast (-> file slurp ns-ast)
-        selected-sexpr (->> ast
-                            (top-level-form-index line column)
-                            (nth ast)
-                            nodes
-                            (filter (partial node-at-loc? line column))
-                            reverse
-                            (drop-while #(#{:local :var :const} (:op %)))
-                            first)]
-    (into '() (set/intersection (->> selected-sexpr :env :locals keys set)
-                                (->> selected-sexpr
+        selected-sexpr-node (->> ast
+                                 (top-level-form-index line column)
+                                 (nth ast)
+                                 nodes
+                                 (filter (partial node-at-loc? line column))
+                                 reverse
+                                 (remove #(#{:local :var :const} (:op %)))
+                                 (sort-by #(- line (-> % :env :line)))
+                                 first)]
+    (into '() (set/intersection (->> selected-sexpr-node :env :locals keys set)
+                                (->> selected-sexpr-node
                                      nodes
                                      (filter #(= :local (:op %)))
                                      (map :form)


correctly access cert

correctly access cert

--- src/org/spootnik/fleet/security.clj
+++ src/org/spootnik/fleet/security.clj
@@ -19,7 +19,7 @@
               cert (.readObject (PEMReader. (io/reader path)))]
           (->
            (doto (Signature/getInstance "SHA256withRSA")
-             (.initVerify cert)
+             (.initVerify (.getPublic cert))
              (.update (.getBytes input)))
            (.verify (-> sig .getBytes b64/decode)))))
       (sign [this input]


added event usage examples

added event usage examples

--- src/test/clojure/naojure/sample.clj
+++ src/test/clojure/naojure/sample.clj
@@ -1,5 +1,8 @@
 (ns naojure.sample
   (:require [naojure.core :as nao :refer []]))
+
+(require '[naojure.core :as nao]
+         '[clojure.core.async :as async :refer [<! >! timeout chan alt! go]])

 ;; examples of how we'd like to control NAO with clojure

@@ -8,9 +11,22 @@

 ;; update with IP address
-(def robot (nao/make-robot "127.0.0.1"))
+(def robot (nao/make-robot "192.168.0.71"))

 (nao/say robot "Hello clojure")
+
+(nao/start-event-loop robot)
+
+(defn evprint [e v] (println "Callback" e v))
+
+(def robot (nao/add-event-handler robot "LeftBumperPressed" evprint))
+
+(def ch1 (async/chan))
+
+(def robot (nao/add-event-chan robot "RightBumperPressed" ch1))
+
+(go (while true (println "Right Bumper" (<! ch1))))
+

 ;; complete movement in default time
 (nao/donao


Made RSS link less hard-coded in the header.

--- src/lambda_blog/templates/page.clj
+++ src/lambda_blog/templates/page.clj
@@ -18,14 +18,14 @@
                  :href (link-or-pathcat path-to-root %)})
        stylesheets))

-(defn header [{:keys [favicon path-to-root scripts stylesheets title]}]
+(defn header [{:keys [favicon path-to-root rss scripts stylesheets title]}]
   (t/head (t/meta {:charset :utf-8})
           (t/title title)
           (css path-to-root stylesheets)
           (t/link {:rel :alternate
                    :type "application/rss+xhtml"
                    :title "RSS Feed"
-                   :href (pathcat path-to-root "index.xml")}) ;; FIXME Pass the string in here somehow.
+                   :href (pathcat path-to-root (:path rss))})
           (t/link {:rel :icon
                    :type "image/png"
                    :href (pathcat path-to-root favicon)})


reverting query order

reverting query order

it was failing due to low memory on the server due to some runaway
processes

--- kabob-build/src/main/resources/edu/ucdenver/ccp/kabob/build/rules/bio_to_bio/part_of.clj
+++ kabob-build/src/main/resources/edu/ucdenver/ccp/kabob/build/rules/bio_to_bio/part_of.clj
@@ -10,11 +10,11 @@
           (?/protein rdfs/subClassOf ?/r)
           )
   :body (
+          (?/loc rdfs/subClassOf obo/GO_0051179) ;localization
+          (?/loc rdfs/subClassOf ?/of1)
+          (?/of1 rdf/type owl/Restriction)
           (?/of1 owl/onProperty obo/RO_0002313) ;transports or maintains localization of
           (?/of1 owl/someValuesFrom ?/protein)
-          (?/of1 rdf/type owl/Restriction)
-          (?/loc rdfs/subClassOf ?/of1)
-          (?/loc rdfs/subClassOf obo/GO_0051179) ;localization

           (?/loc rdfs/subClassOf ?/to1)
           (?/to1 rdf/type owl/Restriction)


Checking if the osx plan even has max minutes set.

--- src-cljs/frontend/models/plan.cljs
+++ src-cljs/frontend/models/plan.cljs
@@ -212,9 +212,10 @@

 (defn current-months-osx-usage-% [plan]
   (let [usage-ms (current-months-osx-usage-ms plan)
-        usage-min (/ usage-ms 1000 60)
-        max-min (-> plan :osx :template :max_minutes)]
-    (.round js/Math (* (/ usage-min max-min) 100))))
+        usage-min (/ usage-ms 1000 60)]
+    (if-let [max-min (-> plan :osx :template :max_minutes) ]
+      (.round js/Math (* (/ usage-min max-min) 100))
+      0)))

 (def first-warning-threshold 75)
 (def second-warning-threshold 95)


For common types do instance checking

For common types do instance checking

Instead of using the lookup method for common types use instance
checks for perf

--- src/longshi/fressian/handlers.cljs
+++ src/longshi/fressian/handlers.cljs
@@ -6,6 +6,10 @@

 (def js-int-type #js{}) ;;Internal marker for JavaScript numbers that are integers
 (def js-int-type-id (.getUid js/goog js-int-type)) ;;Marker code for js-int-type
+(def js-number-type-id (.getUid js/goog js/Number))
+(def js-string-type-id (.getUid js/goog js/String))
+(def js-boolean-type-id (.getUid js/goog js/Boolean))
+(def js-array-type-id (.getUid js/goog js/Array))

 (deftype
   ^{:doc
@@ -61,7 +65,9 @@
   (require-write-handler [wl tag o]
     (let [js-type-id (cond
                        (nil? o) nil
-                       (and (number? o) (zero? (js-mod o 1))) js-int-type-id
+                       (string? o) js-string-type-id
+                       (number? o) (if (zero? (js-mod o 1)) js-int-type-id js-number-type-id)
+                       (array? o) js-array-type-id
                        :else (.getUid js/goog (.-constructor o)))]
       (if-let [handler (-lookup wl js-type-id nil)]
         (if (or (nil? tag) (= tag (.-tag handler)) (= "any" (.-tag handler)))


Update documentation for bind-query-parameters to account for paths

--- src/main/workflo/macros/query.cljc
+++ src/main/workflo/macros/query.cljc
@@ -151,18 +151,20 @@
 (defn bind-query-parameters
   "Takes a parsed query and a map of named parameters and their
    values. Binds the unbound parameters in the query (that is,
-   those where the value is a symbol beginning with a ?) to
-   values of the corresponding parameters in the parameter map
-   and returns the result.
+   those where the value is either a symbol beginning with a ?
+   or a vector of such symbols) to values of the corresponding
+   parameters in the parameter map and returns the result.

    As an example, the :db/id parameter in the query

      [{:name user :type :join
        :join-target [{:name name :type :property}]
-       :parameters {:db/id ?foo}}]
+       :parameters {:db/id ?foo
+                    :user/friend [?bar ?baz]}}]

    would be bound to the value 10 if the parameter map was
-   {:foo 10}."
+   {:foo 10 :bar {:baz :ruux}} and the :user/friend parameter
+   would be bound to the value :ruux."
   [query params]
   (letfn [(var? [x]
             (and (symbol? x)


www/application.clj: call save-static-pages at start

--- src/org/altlaw/www/application.clj
+++ src/org/altlaw/www/application.clj
@@ -8,6 +8,7 @@
             org.altlaw.www.CiteFinder
             org.altlaw.www.AllCasesFinder
             org.altlaw.www.SearchResource
+            org.altlaw.www.content-pages
             [org.altlaw.util.context :as context]
             [org.altlaw.util.solr :as solr]))

@@ -17,6 +18,9 @@
     (.superStart this)
     (.info logger (str "Starting www application with "
                        (context/altlaw-env) " environment."))
+    ;; Generate static content pages:
+    (org.altlaw.www.content-pages/save-static-pages)
+    ;; Start Solr:
     (let [[server core] (solr/start-embedded-solr (context/solr-home))
           attrs (.getAttributes context)]
       (.put attrs "org.altlaw.solr.server" server)


Increase mailserver page size 10 times to make initial sync faster.

Signed-off-by: Igor Mandrigin <042dc4512fa3d391c5170cf3aa61e6a638f84342@mandrigin.ru>

--- src/status_im/mailserver/core.cljs
+++ src/status_im/mailserver/core.cljs
@@ -236,7 +236,7 @@
         mailserver-removed?
         (connect-to-mailserver cofx)))))

-(def limit 200)
+(def limit 2000)

 (defn adjust-request-for-transit-time
   [from]


Update Bahasa Malaysia translation

Update Bahasa Malaysia translation

Translated some more, corrected some misspelling and improved some phrase structure.

--- src/status_im/translations/ms.cljs
+++ src/status_im/translations/ms.cljs
@@ -7,7 +7,7 @@
    :not-implemented                       "!tidak diimplementasikan"
    :chat-name                             "Nama perbualan"
    :notifications-title                   "Pemberitahuan dan bunyi"
-   :offline                               "Offline"
+   :offline                               "Luar talian"
    :search-for                            "Cari..."
    :cancel                                "Batal"
    :next                                  "Seterusnya"
@@ -15,8 +15,8 @@
    :type-a-command                        "Mulakan menaip arahan..."
    :error                                 "Gagal"

-   :camera-access-error                   "Untuk memberi keizinan akses kamera yang diperlukan, sila pegi ke aturan sistem anda dan pastikan bahawa Status > Kamera telah dipilih."
-   :photos-access-error                   "Untuk memberi keizinan akses gambar yang diperlukan, sila pegi ke aturan sistem anda dan pastikan bahawa Status > Gambar telah dipilih."
+   :camera-access-error                   "Untuk memberi keizinan akses kamera yang diperlukan, sila pergi ke aturan sistem anda dan pastikan bahawa Status > Kamera telah dipilih."
+   :photos-access-error                   "Untuk memberi keizinan akses gambar yang diperlukan, sila pergi ke aturan sistem anda dan pastikan bahawa Status > Gambar telah dipilih."

    ;drawer
    :invite-friends                        "Jemput Rakan"
@@ -37,7 +37,7 @@
                                            :other "{{count}} ahli"
                                            :zero  "tiada ahli"}
    :public-group-status                   "Umum"
-   :active-online                         "Online"
+   :active-online                         "Dalam talian"
    :active-unknown                        "Tidak diketahui"
    :available                             "Ada"
    :no-messages                           "Tiada mesej"
@@ -76,10 +76,10 @@

    ;profile
    :profile                               "Profail"
-   :edit-profile                          "Ubah profile"
+   :edit-profile                          "Ubah profail"
    :report-user                           "LAPOR PENGGUNA"
    :message                               "Mesej"
-   :username                              "Nmam pengguna"
+   :username                              "Nama pengguna"
    :not-specified                         "Tidak diberikan"
    :public-key                            "Public key"
    :phone-number                          "Nombor telefon"
@@ -107,34 +107,34 @@
    :sharing-share                         "Kongsi..."
    :sharing-cancel                        "Batal"

-   :browsing-title                        "Browse"
-   :browsing-browse                       "@browse"
-   :browsing-open-in-web-browser          "Buka dalam browser web"
+   :browsing-title                        "Pelayar"
+   :browsing-browse                       "@layar"
+   :browsing-open-in-web-browser          "Buka dalam pelayar web"
    :browsing-cancel                       "Batal"

    ;sign-up
    :contacts-syncronized                  "Senarai kenalan anda telah disegerakan"
-   :confirmation-code                     (str "Terima kasih! Kami telah menghantar kepada anda mesej mengandungi kod"
+   :confirmation-code                     (str "Terima kasih! Kami telah menghantar kepada anda satu mesej mengandungi kod"
                                                "pengesahan. Sila berikan kod tersebut untuk mengesahkan nombor telefon anda")
    :incorrect-code                        (str "Maaf kod salah, sila masukkan sekali lagi")
    :generate-passphrase                   (str "Saya akan mencipta satu ayat pengesahan supaya anda dapat  "
                                                "memulihkan akses atau log masuk dari perangkat baru")
    :phew-here-is-your-passphrase          "*Wah* itu sangatlah susah, ini adalah ayat pengesahan anda, *sila tulis dan pastikan ini selamat!* Anda akan memerlukan ia untuk memulihkan akses ke akaun anda."
    :here-is-your-passphrase               "Ini adalah ayat pengesahan anda, *sila tulis dan pastikan ini selamat!* Anda akan memerlukan ia untuk memulihkan akses ke akaun anda."
-   :written-down                          "Pastikan anda telah menulisnya"
-   :phone-number-required                 "Sentuh disini untu memasukkan nombor telefon anda & saya akan mecari rakan anda"
+   :written-down                          "Sila pastikan anda telah menulisnya"
+   :phone-number-required                 "Sentuh disini untuk memasukkan nombor telefon anda & saya akan mecari rakan anda"
    :shake-your-phone                      "Jumpa kerentanan atau terdapat cadangan? Hanya ~goncang~ telefon anda!"
-   :intro-status                          "Bual dengan saya untuk mencipta akaun anda dan mengubah aturan akaun anda!"
-   :intro-message1                        "Selamat datang ke Status\nSentuh mesej ini untuk menetapkan kata lalaun & memulakan!"
-   :account-generation-message            "Beri saya sedikit masa, saya perlu menyelesaikan masalah matematik yang rumit untuk menciptakan akaun anda!"
+   :intro-status                          "Mulakan perbualan dengan saya untuk mencipta akaun anda dan mengubah aturan akaun anda!"
+   :intro-message1                        "Selamat datang ke Status\nSila sentuh mesej ini untuk menetapkan kata lalaun & memulakan!"
+   :account-generation-message            "Berikan saya sedikit masa, saya perlu menyelesaikan masalah matematik yang rumit untuk menciptakan akaun anda!"
    :move-to-internal-failure-message      "Kita perlu mengubah lokasi sedikit fail penting dari memori dalaman ke memori luaran. Untuk itu, kami perlukan kebenaran anda. Kami tidak akan menggunakan memori luaran pada versi akan datang."
-   :debug-enabled                         "Debug server telah dijalankan! Sekarang anda boleh menjalankan *status-dev-cli scan* untuk mecari sambunagan server dari komputer anda dalam jaringan yang sama."
+   :debug-enabled                         "Debug server telah dijalankan! Sekarang anda boleh menjalankan *status-dev-cli scan* untuk mecari sambungan server dari komputer anda dalam jaringan yang sama."

    ;phone types
-   :phone-e164                            "International 1"
-   :phone-international                   "International 2"
-   :phone-national                        "National"
-   :phone-significant                     "Significant"
+   :phone-e164                            "Internasional 1"
+   :phone-international                   "Internasional 2"
+   :phone-national                        "Nasional"
+   :phone-significant                     "Penting"

    ;chats
    :chats                                 "Perbualan"
@@ -149,7 +149,7 @@
    :public-group-topic                    "Topik"

    ;discover
-   :discover                              "Temui"
+   :discover                              "Jelajah"
    :none                                  "Tiada"
    :search-tags                           "Taip carian anda disini"
    :popular-tags                          "Popular"
@@ -165,14 +165,14 @@
    :new-contact                           "Kenalan baru"
    :delete-contact                        "Padam kenalan"
    :delete-contact-confirmation           "Kenalan ini akan dipadam dari senarai kenalan anda"
-   :remove-from-group                     "Buang dari kumpualan"
+   :remove-from-group                     "Buang dari kumpulan"
    :edit-contacts                         "Ubah kenalan"
    :search-contacts                       "Cari kenalan"
    :show-all                              "TUNJUK SEMUA"
    :contacts-group-dapps                  "ÐApps"
-   :contacts-group-people                 "Pegguna"
+   :contacts-group-people                 "Pengguna"
    :contacts-group-new-chat               "Mulakan perbualan baru"
-   :choose-from-contacts                  "Pilih dri kenalan"
+   :choose-from-contacts                  "Pilih dari kenalan"
    :no-contacts                           "Masih tiada kenalan"
    :show-qr                               "Tunjuk kod QR"
    :enter-address                         "Masukkan address"
@@ -184,7 +184,7 @@
    :delete                                "Padam"
    :change-color                          "Tukar warna"
    :clear-history                         "Padam sejarah perbualan"
-   :mute-notifications                    "Perberitahuan mod senyap"
+   :mute-notifications                    "Pemberitahuan senyap"
    :leave-chat                            "Tinggalkan perbualan"
    :delete-and-leave                      "Padam dan tinggalkan"
    :chat-settings                         "Aturan perbualan"
@@ -239,16 +239,16 @@

    ;new-contact
    :add-new-contact                       "Tambah kenalan baru"
-   :import-qr                             "Impot"
+   :import-qr                             "Impot kod QR"
    :scan-qr                               "Imbas kod QR"
    :swow-qr                               "Tunjuk kod QR"
    :name                                  "Nama"
-   :whisper-identity                      "Whisper Identity"
-   :address-explication                   "Mungkin disini sepatutnya tedapat sedikit teks menjelaskan apa itu address dan dimana untuk melihatnya"
+   :whisper-identity                      "Identiti Whisper"
+   :address-explication                   "Mungkin disini sepatutnya terdapat sedikit teks menjelaskan apa itu address dan dimana untuk melihatnya"
    :enter-valid-address                   "Sila masukkan address yang sah atau imbas satu kod QR"
-   :enter-valid-public-key                "Sila masukkan public key yang sah atau imbas satu kod QR"
+   :enter-valid-public-key                "Sila masukkan public key yang sah atau imbas kod QR"
    :contact-already-added                 "Kenalan telah ditambah"
-   :can-not-add-yourself                  "Anda tidak boleh menbah diri anda sendiri"
+   :can-not-add-yourself                  "Anda tidak boleh menambah diri anda sendiri"
    :unknown-address                       "Address tidak diketahui"

@@ -256,14 +256,14 @@
    :connect                               "Sambung"
    :address                               "Address"
    :password                              "Kata laluan"
-   :login                                 "Log masuk"
-   :sign-in-to-status                     "Sign in ke Status"
-   :sign-in                               "Sign in"
+   :login                                 "Daftar masuk"
+   :sign-in-to-status                     "Daftar masuk ke Status"
+   :sign-in                               "Daftar masuk"
    :wrong-password                        "Kata laluan salah"

    ;recover
    :recover-from-passphrase               "Pulihkn akaun daripada ayat pengesahan"
-   :recover-explain                       "Sila masukkan ayat pengesahan kepada kata laluan anda untuk memulihkan akse ke akaun anda"
+   :recover-explain                       "Sila masukkan ayat pengesahan kepada kata laluan anda untuk memulihkan akses ke akaun anda"
    :passphrase                            "Ayat pengesahan"
    :recover                               "Pulihkan"
    :enter-valid-passphrase                "Sila masukkan ayat pengesahan"
@@ -295,8 +295,8 @@
    :transaction                           "Transaksi"
    :unsigned-transactions                 "Transaksi tidak berdaftar"
    :no-unsigned-transactions              "Tiada transaksi tidak berdaftar"
-   :enter-password-transactions           {:one   "Sahkan transaksi dengan memasukkan kata laluan anda"
-                                           :other "Sahkan transaksi dengan memasukkan kata laluan anda"}
+   :enter-password-transactions           {:one   "Sila sahkan transaksi dengan memasukkan kata laluan anda"
+                                           :other "Sila sahkan transaksi dengan memasukkan kata laluan anda"}
    :status                                "Status"
    :pending-confirmation                  "Pengesahan belum selesai"
    :recipient                             "Penerima"
@@ -308,7 +308,7 @@
    :from                                  "Dari"
    :data                                  "Maklumat"
    :got-it                                "Ya"
-   :contract-creation                     "Ciptaan kontrak"
+   :contract-creation                     "Cipta kontrak"

    ;:webview
    :web-view-error                        "oops, gagal"})


SER-2525 | make path in metrics consistent

--- src/vignette/http/route_helpers.clj
+++ src/vignette/http/route_helpers.clj
@@ -41,7 +41,7 @@
       (perf/publish {:exception-count 1})
       (log/warn (str e) {:path  (:uri request)
                          :query (:query-string request)})
-      (create-response 500 "Server Error" {:path "delete"}))))
+      (create-response 500 "Server Error" {:path "original"}))))

 (defn handle-delete
   [store image-params request]


Add alias name to its docs

Add alias name to its docs

--- src/yetibot/core/commands/alias.clj
+++ src/yetibot/core/commands/alias.clj
@@ -39,7 +39,7 @@
    Use first arg only:
    alias sayhi = echo hi, $1"
   [{:keys [cmd-name cmd]}]
-  (let [docstring (str "alias for " cmd)
+  (let [docstring (str cmd-name " # alias for " cmd)
         existing-alias (existing-alias cmd-name)
         cmd-fn (build-alias-cmd-fn cmd)]
     (cmd-hook [cmd-name (re-pattern (str "^" cmd-name "$"))]