Vogelalbum 1.0.0
Eine Kamera am Vogelhaus, ein Rechner der erkennt wer da war — und eine Sammlung, die sich von allein fuellt. Zwei neuronale Netze: eines findet den Vogel im Bild, eines bestimmt die Art. 148 heimische Arten, auf Deutschland eingeschraenkt und neu normiert — ohne diese Einschraenkung wird aus einer Kohlmeise eine nordamerikanische Schwesterart. Daraus entsteht ein Sammelalbum: nummerierte Seiten, gefundene Arten in Farbe, fehlende als Schatten, dazu Erstfang, Punkte, Stufen und 15 Abzeichen. Laeuft vollstaendig auf eigener Hardware. Kein Cloud-Dienst, kein Konto, keine Telemetrie; die Bilder verlassen das eigene Netz nicht. Zwei getrennt deploybare Teile: die Sammlung als Django-Anwendung, die Erkennung als eigener Dienst. Der Erkennungs-Dienst fragt selbst an und braucht deshalb weder eine erreichbare Adresse noch einen offenen Port — er laeuft hinter einem gewoehnlichen Router. Dabei: Firmware fuer Raspberry Pi und ESP32-S3, Anbindung an Home Assistant ueber MQTT, Oberflaeche auf Deutsch und Englisch, Einstellungen je Kamera aus dem Browser, und ein Weg fuer Fotos von unterwegs. AGPL-3.0.
This commit is contained in:
commit
c11fe9ab04
189 files changed
+29806
No files matched your search
@@ -0,0 +1,74 @@
|
||||
{% extends "dex/base.html" %}
|
||||
{% load i18n dex_extras %}
|
||||
|
||||
{% block title %}{% trans "Abzeichen" %} — Vogelalbum{% endblock %}
|
||||
|
||||
{% block kopf %}
|
||||
<style>
|
||||
/* ⚠ Eigene Klassen statt der xp-track vom Kopfbereich: Die ist dort
|
||||
breit und hoch, hier soll der Balken in eine Abzeichenkarte passen
|
||||
ohne sie auseinanderzuziehen. */
|
||||
.fortschritt {
|
||||
margin-top: 8px;
|
||||
height: 6px;
|
||||
border-radius: 999px;
|
||||
background: color-mix(in srgb, var(--text) 12%, transparent);
|
||||
overflow: hidden;
|
||||
}
|
||||
.fortschritt-fuellung {
|
||||
height: 100%;
|
||||
border-radius: 999px;
|
||||
background: var(--accent);
|
||||
/* Auch bei 0 % ein Hauch sichtbar -- sonst sieht die Karte aus,
|
||||
als fehlte der Balken. */
|
||||
min-width: 3px;
|
||||
}
|
||||
.fortschritt-text {
|
||||
margin-top: 4px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
/* Die Karte ist abgeblendet, solange das Abzeichen fehlt. Der Balken
|
||||
soll trotzdem lesbar bleiben -- er ist ja der Grund hinzuschauen. */
|
||||
.badge.locked .fortschritt-fuellung { opacity: .85; }
|
||||
</style>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h2>{% trans "Abzeichen" %} <span class="count">{% blocktrans with n=progress.badges %}{{ n }} verdient{% endblocktrans %}</span></h2>
|
||||
|
||||
<div class="badges">
|
||||
{% for row in rows %}
|
||||
<div class="badge {% if not row.earned %}locked{% endif %}">
|
||||
{% abzeichen_bild row.badge.code as pin %}
|
||||
{% if pin %}
|
||||
<img class="em" src="{{ pin }}" alt="" width="72" height="72" loading="lazy">
|
||||
{% else %}
|
||||
<div class="em">{{ row.badge.emoji }}</div>
|
||||
{% endif %}
|
||||
<div>
|
||||
<div class="n">{{ row.badge.name_lokal }}</div>
|
||||
<div class="d">{{ row.badge.description_lokal }}</div>
|
||||
<div class="d" style="margin-top:6px; color:var(--accent-dim); font-weight:700">
|
||||
{% if row.earned %}{{ row.at|date:"SHORT_DATE_FORMAT" }} · +{{ row.badge.xp }} XP{% else %}+{{ row.badge.xp }} XP{% endif %}
|
||||
</div>
|
||||
|
||||
{% comment %}
|
||||
🔑 Balken nur, wo es etwas zu zaehlen gibt. Bei "Ein Specht war da"
|
||||
stuende er dauerhaft auf null und waere keine Information.
|
||||
⚠️ {# … #} ist in Django EINZEILIG — mehrzeilig braucht es comment,
|
||||
sonst steht der Text sichtbar auf der Seite.
|
||||
{% endcomment %}
|
||||
{% if row.ziel %}
|
||||
<div class="fortschritt" title="{{ row.ist }} von {{ row.ziel }}">
|
||||
<div class="fortschritt-fuellung" style="width: {{ row.anteil }}%"></div>
|
||||
</div>
|
||||
<div class="d fortschritt-text">{{ row.ist }} / {{ row.ziel }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
Reference in new issue
Block a user