solarbatteryield/
├── src/solarbatteryield/ # Application source code
│ ├── __init__.py
│ ├── streamlit_app.py # Main entry point
│ ├── simulation.py # Core simulation engine
│ ├── models.py # Data classes
│ └── ...
├── tests/ # Test suite
│ ├── test_simulation.py # Unit tests
│ ├── test_snapshots.py # Snapshot regression tests
│ ├── test_smoke.py # Smoke tests
│ └── __snapshots__/ # Pinned snapshot data
├── pyproject.toml # Project configuration
└── uv.lock # Dependency lock file
git clone https://github.com/markusdlugi/solarbatteryield.git
cd solarbatteryield
uv sync --dev
uv run streamlit run src/solarbatteryield/streamlit_app.py| Variable | Beschreibung | Default |
|---|---|---|
NOMINATIM_ENABLED |
Aktiviert Geocoding (Ortssuche). Standardmäßig deaktiviert, um Rate-Limits bei der Entwicklung zu vermeiden. | false |
NOMINATIM_EMAIL |
E-Mail-Adresse für Nominatim-Anfragen. Pflicht, wenn Geocoding aktiviert ist. | – |
Hinweis: Das Geocoding ist bewusst standardmäßig deaktiviert. Wenn
NOMINATIM_ENABLED=truegesetzt wird, aberNOMINATIM_EMAILfehlt, wirft die App einen Fehler. Dies verhindert, dass Requests ohne E-Mail-Adresse gesendet werden, was zu Blockierungen durch Nominatim führen kann.
export NOMINATIM_ENABLED=true
export NOMINATIM_EMAIL="your-email@example.com"
uv run streamlit run src/solarbatteryield/streamlit_app.pyOder in .streamlit/secrets.toml:
NOMINATIM_ENABLED = "true"
NOMINATIM_EMAIL = "your-email@example.com"In den App-Einstellungen unter Settings > Secrets:
NOMINATIM_ENABLED = "true"
NOMINATIM_EMAIL = "your-email@example.com"# Run all tests
uv run pytest
# Run specific test files
uv run pytest tests/test_simulation.py -vNach Änderungen an der Simulationslogik oder den Ausgabeformaten müssen die Snapshot-Tests aktualisiert werden, um die
neuen erwarteten Ergebnisse zu reflektieren. Dies geschieht mit dem --snapshot-update Flag:
uv run pytest tests/test_snapshots.py --snapshot-updateDieses Projekt verwendet Conventional Commits für automatisches Versioning und Release Notes.
<type>(<scope>): <description>
[optional body]
[optional footer(s)]
| Typ | Beschreibung | Version-Bump |
|---|---|---|
feat: |
Neues Feature für Nutzer | Minor |
fix: |
Bugfix für Nutzer | Patch |
perf: |
Performance-Verbesserung | Patch |
refactor: |
Code-Änderung ohne Funktionsänderung | Patch |
docs: |
Nur Dokumentation | Kein Release |
style: |
Formatierung, Whitespace, etc. | Kein Release |
test: |
Tests hinzufügen/ändern | Kein Release |
chore: |
Build-Prozess, Dependencies, etc. | Kein Release |
ci: |
CI/CD-Änderungen | Kein Release |
build: |
Build-System oder externe Dependencies | Kein Release |
BREAKING CHANGE |
Breaking Change (im Footer oder mit ! nach Type) |
Major |
feat(simulation): add support for AC-coupled batteries
fix(api): handle PVGIS timeout gracefully
feat(models)!: change ModuleConfig to use dataclass
BREAKING CHANGE: ModuleConfig is now a dataclass instead of a dict.
oder:
refactor(simulation): redesign energy flow calculation
BREAKING CHANGE: Simulation results now use different field names.
docs: update README with new screenshots
chore: update dependencies
test: add unit tests for H0 profile
ci: add Python 3.13 to test matrix
Der Scope beschreibt den betroffenen Bereich:
feat(sidebar): add battery coupling toggle
fix(report): correct currency formatting
perf(simulation): optimize hourly loop
refactor(models): extract common validation logic
Bei mehreren Änderungen in einem Commit gilt die "höchste" Änderung:
- BREAKING CHANGE > feat > fix/perf/refactor > andere
Empfehlung: Mache kleine, fokussierte Commits mit einem klaren Typ.
Bei jedem Push auf master:
- Tests werden ausgeführt
- Commit-Messages werden analysiert
- Version wird automatisch erhöht (falls relevantem Commit-Typ)
- Release Notes werden aus den Commits generiert
- GitHub Release wird erstellt mit Tag
docs:,style:,test:,chore:,ci:,build:Commits- Commits ohne Conventional-Commit-Prefix
chore(release):Commits (um Endlosschleifen zu vermeiden)