feat(gasmessung): up to 8 gases, with unit and bands from the Stammdaten
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 5/5
- 预计耗时
- 一周以上
- 新手友好度
- 25/100
调研方向
Start with the listed entry points: Domain/CoMeasurement and Incident.cs, then trace persistence, Sync, CoMessprotokollViewModel.cs, CoMessprotokollView.axaml, and Documents/Sections/CoMessprotokollSection.cs. Review issue #403 for threshold configuration and #404 for PDF layout constraints before deciding the design. Done means multi-gas values, units, colors, sync, PDF output, and loading legacy CO data are handled; the issue also leaves key design choices open.
由索引模型根据 Issue 内容生成。
描述
Today
The Messprotokoll records exactly one value per Wohnung: Dwelling.CoValue, an int? in ppm,
plus its Messreihe of CoReading(MeasuredAt, int? Value, RecordedBy) (#424). The colour bands
are three constants in CoSeverityClassifier (30/200/800 ppm, plausibility limit 2000).
Crews enter the building with multi-gas meters, which show CO₂, H₂S, CH₄ (%UEG) and O₂ next
to CO. Every gas except CO ends up in the ETB free text at best. None of them reach the matrix
or the Bericht, and the matrix and the Bericht are where the Einsatzleiter looks.
Proposal
1. The gases are Stammdaten
A new Stammdaten category Messgase (top-level Gases in MasterDataSet / MasterDataJson)
holds at most 8 entries. A brigade measures with the same meters every time, so the list is
set up once rather than typed in for each Einsatz.
| Field | Meaning |
|---|---|
| Name | short label shown in tile, editor, ETB and PDF, e.g. CO, H2S, O2 (length-capped) |
| Einheit | free text; suggestions ppm / %UEG / Vol-% / mg/m³ |
| Richtung | steigend (higher is worse) or fallend (lower is worse, for O₂) |
| Erhöht / Gefährlich / Lebensgefährlich | up to three thresholds, decimal, each optional, ordered in the gas's direction |
| Plausibel bis | optional; a value beyond it gets the existing "check this" hint and is never rejected |
- Default: a store without
Gasesyields exactly today's single gas:CO,ppm, steigend,
30/200/800, plausible up to 2000. A brigade that never opens the new tab sees no change. - No thresholds, no colour: a gas with no thresholds is recorded and shown in neutral. It is
never shown in a colour it has not earned. - The import is hostile input:
- more than 8 gases, an over-long name or unit, a non-finite number or thresholds out of
order are rejected or capped on import; - the editor enforces the same limits.
- more than 8 gases, an over-long name or unit, a non-finite number or thresholds out of
docs/master-data.example.jsongains a full example: CO, CO₂, H₂S, CH₄ (%UEG), and O₂ (Vol-%,
fallend, 19/17/10).
This replaces the built-in name-matched thresholds that the original proposal had. It also covers
the CO-band half of #403: the bands are no longer pegged to the German AGW in code, because
every brigade sets its own.
2. The incident copies the list when it is first used
Per AGENTS.md Stammdaten in an incident, the incident stores values, never a reference into
the Stammdaten.
- When an Einsatz opens its first Haus in the Gasmessung, it copies the Stammdaten gas list into
its own table: name, unit, direction, thresholds, plausibility limit and order. - That copy is what the file shows from then on. It still shows it after the Stammdaten are
edited, on another Feuerwehr's machine, or years later. - The list order is the display order everywhere.
- Changing an Einsatz's gas list after it has been copied is out of scope.
3. A value per gas, with a unit and decimals
- Each Wohnung has a current value per gas and one Messreihe per gas.
CoReadinggains the gas, an id into the incident's own gas table, and its value becomes
decimal. 20.9 Vol-% O₂ cannot be stored as anintppm.- Values are formatted in
de-DEfor display (20,9 Vol-%) and stored in invariant culture. - The editor sidebar shows one input per gas of the Einsatz, each with its unit as a suffix.
- FERTIG records one reading for each gas that changed and writes one ETB entry naming
them all:
Gasmessung Haus A, 2. OG, Whg. 1: CO 120 ppm, H2S 3 ppm
4. The colour is the worst gas
- A tile's colour is the highest severity across all its gases. The order is Lebensgefährlich > Gefährlich > Erhöht > Normal,
each gas judged against its own thresholds in its own direction. - The tile shows the reading that decided the colour, e.g.
H2S 12 ppm. On a tie, the gas
earlier in the list wins. - While every gas is normal, the tile shows the first measured gas in list order.
- An Einsatz with only one gas leaves out the gas name, so a CO-only Einsatz looks exactly as it
does today. - The tooltip and the detail sidebar list every gas, each in its own colour.
- Floor and Haus summaries use the same worst-gas rule.
5. "CO-Messung" becomes "Gasmessung"
- The rail entry changes from
CO-MessungtoGasmessung. - The PDF section and the PDF export option change from
CO-MessprotokolltoGasmessprotokoll. - The ETB texts change from
CO-Messprotokoll eröffnet/entfernt: …to
Gasmessprotokoll eröffnet/entfernt: …. - The navigation key
co(NavModules.Co) stays as it is. It is stored in every brigade's
Stammdaten navigation, so changing it would orphan their entries. - Code identifiers (
CoMessprotokollViewModel,co_*tables) stay in this issue to keep the diff
reviewable. Renaming them is a separate refactor.
6. Bericht
The Gasmessprotokoll section replaces the single ppm column with one Messwerte column. It
lists each Wohnung's non-empty gas values (CO 120 ppm · H2S 3 ppm), each value in its own band
colour. Eight gases fit on A4 portrait this way without waiting on #404. The Messreihe rows
(#424) name the gas.
Affected areas
| Layer | What |
|---|---|
Persistence/MasterData |
Gas record + Gases in MasterDataSet/MasterDataJson, defaults, import validation; Stammdaten store needs no migration |
App.Shared / AppLogic Stammdaten editor |
new Messgase tab (max 8, direction picker, ordered thresholds) |
Domain/CoMeasurement |
incident gas list; per-gas values on Dwelling; CoReading + gas, decimal value; classifier takes a gas definition + value, returns the worst severity over a Wohnung |
Domain/Incident.cs |
copy the gas list when the first Haus opens; RecordCoValue takes the gas; one ETB entry per FERTIG |
Persistence/Sqlite |
migration (V28 now, renumber above main at merge): incident gas table, gas column on readings, per-gas current values; register in SchemaGuard.ExpectedColumns |
Sync |
gas list in IncidentSnapshot; the record command carries gas + decimal value. A peer at the floor cannot handle it, so raise MinimumProtocolVersion with ProtocolVersion (renumber above main at merge) |
AppLogic/ViewModels/CoMessprotokollViewModel.cs |
per-gas inputs, worst-gas tile state, tooltip/summary per gas |
App.Shared/Views/CoMessprotokollView.axaml |
up to 8 inputs; tile shows deciding gas; must still work on a phone |
Documents/Sections/CoMessprotokollSection.cs |
Messwerte column, gas in the Messreihe |
NavigationSection, PdfExportOptionsViewModel |
the rename |
docs/master-data.example.json |
Messgase example |
Compatibility
- Files saved before this feature: an Einsatz saved earlier has exactly one gas,
CO,ppm,
steigend, 30/200/800, and comes out that way on load without asking. The migration writes that
gas into the incident's own table and movesco_valueand the existing Messreihe onto it.
Nothing is lost, and nothing reads "unnamed gas". A forward-compat test like the existing ones
covers this. - A joined client with different Stammdaten shows the host's copied gas list, which comes from
the snapshot. The client's own catalogue has no say.
Decided (were open questions)
- The cap is a hard limit of 8. It is enforced in the Stammdaten editor, on import, and on the
copied incident list that arrives from a file or a sync peer. - The matrix shows the worst gas. The colour and value come from the worst gas; every other
value is in the tooltip and the sidebar. - The gas list is Stammdaten, copied into the incident when it is first used.
Out of scope
- O₂ enrichment (> 23 Vol-%). A gas has one direction.
- Editing an Einsatz's gas list after it has been copied.
- Renaming the
Co*code identifiers andco_*tables. - Floor labels (EG/OG/UG). They stay in #403.
- 主要语言
- C#
- 星标
- 1
- 派生
- 3
- 平均合并
- 4 小时 15 分钟
- 30 天内合并 PR
- 181
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
CodeForFire/lagebuch 的其他 Issue
-
Stammdaten: in the Checkliste editor the PFLICHT header is not aligned with its column可能已有人在做 @Saad-elnagar 于 2 天前认领。 未关闭bug ux
难度 2/5 1-3 小时 新手友好度 78/100
CodeForFire/lagebuch#714 · 1 条评论 ·
维护者通常 1 天内回复
-
Stammdaten: on a phone the Fahrzeuge editor squeezes Wache and Funkrufname to nothing可能已有人在做 @Saad-elnagar 于 2 天前认领。 未关闭bug ux
难度 2/5 1-3 小时 新手友好度 75/100
CodeForFire/lagebuch#713 · 1 条评论 ·
维护者通常 1 天内回复
-
enhancement
难度 2/5 1-3 小时 新手友好度 62/100
CodeForFire/lagebuch#405 ·
维护者通常 1 天内回复
-
documentation good first issue
难度 2/5 1-3 小时 新手友好度 88/100
CodeForFire/lagebuch#349 ·
维护者通常 1 天内回复
-
documentation good first issue
难度 2/5 1-3 小时 新手友好度 88/100
CodeForFire/lagebuch#348 ·
维护者通常 1 天内回复
查看 CodeForFire/lagebuch 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 76/100
Nimblesite/SharpLsp#468 ·
维护者通常 1 天内回复
-
alerts bug effort:S P2
难度 2/5 1-3 小时 新手友好度 76/100
nightscout/nocturne#2511 ·
维护者通常 1 天内回复
-
good first issue
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 1 天内回复
-
feature-request
难度 2/5 1-3 小时 新手友好度 77/100
stripe/stripe-dotnet#3484 ·
维护者通常 2 天内回复
-
bug mcp misleading small
难度 2/5 1-3 小时 新手友好度 77/100
维护者通常 1 天内回复