# Einstellungen und Ziele Status: ready-for-agent ## Problem Statement The Karte keeps one Ziel, drops it when the page is left, and treats a download as a Gebiet marked heruntergeladen. The person cannot keep several places, return to one of them, or save just the view they are looking at. Removing Hessen is a separate action from clearing the Cache, and an unfinished Hessen download continues by itself the next time the app opens. ## Solution Einstellungen hold a Download-Knopf switch, the red Hessen download, and deletion of the whole Cache. When the switch is on, a download control on the Karte fetches the Kacheln of the current view at every prepared scale into the Cache. Downloads do not mark a Gebiet. Ziele are a list of red points the person adds, revisits, and deletes, and they stay on the device until the person deletes them. ## User Stories 1. As a person using the Karte, I want an Einstellungen control where Cache used to be, so that download and Cache actions sit together. 2. As a person using the Karte, I want Einstellungen to start collapsed, so that the Karte is the first thing I see. 3. As a person using the Karte, I want the first control inside Einstellungen to be a checkbox labelled Download-Knopf, so that I can choose whether a download control sits on the Karte. 4. As a person using the Karte, I want that checkbox to start off the first time, so that the Karte opens without an extra control. 5. As a person using the Karte, I want the device to remember the checkbox, so that I do not set it again after reopening. 6. As a person using the Karte, I want a download control at the bottom right of the Karte while the checkbox is on, so that I can fetch the view I am looking at. 7. As a person using the Karte, I want that control to stay while Einstellungen are collapsed, so that I do not have to keep the panel open. 8. As a person using the Karte, I want the control hidden while the checkbox is off, so that the Karte stays clear. 9. As a person using the Karte, I want Hessen herunterladen inside Einstellungen, so that the full download lives with the other Cache actions. 10. As a person using the Karte, I want Hessen herunterladen to stay those words, so that the control does not turn into a delete. 11. As a person using the Karte, I want Hessen herunterladen drawn red while any Kachel of Hessen is missing from the Cache, so that the unfinished download is obvious. 12. As a person using the Karte, I want Hessen herunterladen disabled once every Kachel of Hessen is in the Cache, so that I cannot start a finished download. 13. As a person using the Karte, I want the disabled Hessen control shown as disabled, so that it is distinct from the red active control. 14. As a person using the Karte, I want Ganzen Cache löschen inside Einstellungen, so that wiping Kacheln lives with the downloads. 15. As a person using the Karte, I want to be asked "Den ganzen Cache löschen?" before the Cache is wiped, so that I do not clear it by mistake. 16. As a person using the Karte, I want declining that question to leave the Cache as it is, so that cancel is safe. 17. As a person using the Karte, I want a wiped Cache to make Hessen herunterladen red and active again, so that I can fetch Hessen once more. 18. As a person using the Karte, I want a wiped Cache to leave my Ziele and the Download-Knopf checkbox as they are, so that clearing pixels does not clear places I named. 19. As a person using the Karte, I want Hessen herunterladen to fetch only Kacheln of Hessen that are not yet in the Cache, so that a second run finishes the remainder. 20. As a person using the Karte, I want those Kacheln to cover every prepared scale, from 1.25 m per pixel up to the 36 km span, so that offline zoom has the pixels it needs. 21. As a person using the Karte, I want the Kacheln of the scale I am looking at to arrive before the other Hessen Kacheln, so that the place on screen fills first. 22. As a person using the Karte, I want a second press of Hessen herunterladen, while that fill is already running, to add nothing further, so that the button cannot restart the same work. 23. As a person using the Karte, I want the download control on the Karte to fetch every Kachel that intersects the view at the moment I press it, at every prepared scale, so that I can zoom that place offline. 24. As a person using the Karte, I want that set of Kacheln fixed at the press, so that panning afterwards does not enlarge the request. 25. As a person using the Karte, I want a wide view to fetch the fine Kacheln inside it as well, so that "every scale" includes a view zoomed out to the 36 km span. 26. As a person using the Karte, I want Kacheln already in the Cache to be skipped, so that the press only fetches what is missing. 27. As a person using the Karte, I want a press that finds nothing missing to fetch nothing, so that a finished view stays quiet. 28. As a person using the Karte, I want a second press of the same download control, while that view fill is already running, to add nothing further, so that the control cannot restart the same work. 29. As a person using the Karte, I want Hessen and the view fill to share one queue, so that the device fetches one Kachel at a time. 30. As a person using the Karte, I want Kacheln of the current view's scale to go first when both fills are active, so that the place on screen still fills before the rest. 31. As a person using the Karte, I want Einstellungen to show how many of the Kacheln requested in this visit have arrived, while a fill is running, so that a long download is not silent. 32. As a person using the Karte, I want a network drop while the app stays open to pause the fill, and the return of the network to continue it, so that a short gap does not cancel the visit's request. 33. As a person using the Karte, I want leaving the app to stop the fill, so that the phone does not keep fetching in the background. 34. As a person using the Karte, I want opening the app to leave that fill stopped, so that a download continues only when I press again. 35. As a person using the Karte, I want a later press to fetch the Kacheln that are still missing, so that finished Kacheln are kept. 36. As a person using the Karte, I want looking around, while online and the app is open, to fetch only the Kacheln of the current view at the current scale, so that panning does not pull every scale. 37. As a person using the Karte, I want a Kachel already in the Cache to be drawn while a fill continues, so that the finished part of the Karte is usable. 38. As a person using the Karte, I want no fetch while the device is offline, so that a blank Kachel stays blank until a connection exists. 39. As a person using the Karte, I want a Ziele section beside Einstellungen, so that naming places stays separate from downloads. 40. As a person using the Karte, I want Ziele to start open, so that the Koordinate fields are where they were. 41. As a person using the Karte, I want to type a Koordinate as Gitter, Rechtswert, and Hochwert, with Gitter starting as `32U MA`, so that the usual square is ready. 42. As a person using the Karte, I want a valid Koordinate to add a Ziel, so that a second place does not erase the first. 43. As a person using the Karte, I want each Ziel drawn in red, so that every named place is visible. 44. As a person using the Karte, I want the new Ziel at the top of the list, so that the place I just named is the first row. 45. As a person using the Karte, I want each row to show that Ziel's Koordinate, so that I can read the place without guessing from the dot. 46. As a person using the Karte, I want the Entfernung after the Koordinate when a Standort is known, so that I can compare how far each Ziel is. 47. As a person using the Karte, I want that Entfernung in metres below 1000 m and in kilometres from 1000 m, so that the number stays readable. 48. As a person using the Karte, I want each Entfernung to update as the Standort moves, so that the list stays current while I walk. 49. As a person using the Karte, I want rows to show only the Koordinate when no Standort is known, so that I am not shown a distance to nowhere. 50. As a person using the Karte, I want a new Ziel to center the view on it at 1:25,000, even while its Kacheln are blank, so that I see the place I named. 51. As a person using the Karte, I want tapping a row to center that Ziel at 1:25,000, so that I can return to it after panning. 52. As a person using the Karte, I want Auf Standort to remain, so that I can still return to myself at 1:25,000. 53. As a person using the Karte, I want no Auf Ziel control, so that no single Ziel is treated as the special one. 54. As a person using the Karte, I want a Löschen control on each row, so that I can remove that Ziel without moving the view. 55. As a person using the Karte, I want Löschen to remove that Ziel without a question, so that deleting one place is the action itself. 56. As a person using the Karte, I want the same Koordinate only once, so that two dots cannot occupy one cell. 57. As a person using the Karte, I want a repeated Koordinate explained in German, leaving the list and the view unchanged, so that a duplicate is not a second Ziel. 58. As a person using the Karte, I want an invalid Koordinate, or one that no Blatt covers, explained in German, leaving the list and the view unchanged, so that a mistake does not drop places I already have. 59. As a person using the Karte, I want the typed fields to stay after a successful entry, so that I can check them against the new row. 60. As a person using the Karte, I want Ziele to remain on the device until I delete them, so that leaving or reloading the page keeps the list. 61. As a person using the Karte, I want a tap on the Karte within 44 px of a Ziel to delete the nearest one, so that I can remove a dot where it sits. 62. As a person using the Karte, I want that tap to do this at every scale, so that "near" means near on the screen. 63. As a person using the Karte, I want a tap farther than 44 px from every Ziel to add a Ziel at that point, written as a Koordinate to the metre, so that I can name a place without typing. 64. As a person using the Karte, I want that added Ziel at the top of the list, without moving the view, so that the Karte stays where I tapped. 65. As a person using the Karte, I want a tap on the Standort to add a Ziel there when no Ziel is within 44 px, so that my own position can become a named place. 66. As a person using the Karte, I want a tap on a point no Blatt covers to leave the list and the view unchanged, so that a hole between Blätter cannot become a Ziel. 67. As a person using the Karte, I want a drag to pan the Karte, so that moving the view is not naming a Ziel. 68. As a person using the Karte, I want this tap behavior without a separate mode, so that the Karte always accepts it. 69. As a person using the Karte, I want the Standort to stay blue and to stay unstored, so that my own position is still the device's, only while the app is open. 70. As a person using the Karte, I want a late first Standort, after I have panned or added a Ziel, to move only the blue mark, so that my view is not yanked away. ## Implementation Decisions - Follow ADR 0001 and ADR 0003. A download writes missing Kacheln into the Cache and does not mark a Gebiet. ADR 0002 is superseded and is not implemented. - The screen talks only to a Karte session. That session is the one test seam. Map drawing, the browser position API, and device storage sit behind it. ### Session contract The screen and the tests share these names. A Ziel on the snapshot is `{ koordinate, point, entfernung }`. `koordinate` is the canonical writing: Gitter uppercased with one space (`32U MA`), plus the five-digit Rechtswert and Hochwert. `entfernung` is `{ metres, text }` in the existing German form, or `null` when no Standort is known. `ziele` is newest first. `snapshot()` returns `center`, `resolution`, `northUp`, `ziele`, `standort`, `notice`, `koordinate` (the typed fields, unchanged by success or failure), `downloadKnopf`, `hessen: { arrived, total }`, `visit: { arrived, total } | null`, and `kacheln`. There is no single Ziel, no single Entfernung, and no heruntergeladen flag. `hessen.arrived` counts Hessen Kacheln in the Cache. `visit` is set only while a Hessen or view fill from this visit is unfinished; after it finishes, and after the app is closed, `visit` is `null`. `enterKoordinate` adds when the text is valid, a Blatt covers the point, and that canonical Koordinate is not already a Ziel. A repeat sets `notice` to `Diese Koordinate ist schon ein Ziel.` and changes nothing else. The existing German notices stay for an invalid Koordinate and for a point no Blatt covers. Success clears `notice`, appends the Ziel at the front, and centers at 1:25,000. `deleteZiel(koordinate)` and `centerOnZiel(koordinate)` address one Ziel by that canonical Koordinate. Delete does not move the view and does not ask. `centerOnZiel` and `centerOnStandort` both use 1:25,000. `tap(point)` uses the session's current scale. The radius is 44 screen pixels times metres per pixel, inclusive. The nearest Ziel inside it is deleted; a tie deletes the newer Ziel. Otherwise the point is added as a Koordinate to the metre, under the same Blatt and uniqueness rules, and the view stays. A point no Blatt covers changes nothing, including `notice`. The Standort is not a Ziel. `setDownloadKnopf` stores the checkbox. `startHessen` and `downloadView` are the two fill kinds. A second call of the same kind, while that kind is unfinished, adds no Kacheln. The other kind still adds its missing Kacheln. Both share one queue with on-demand fetches: one Kachel at a time, and Kacheln of the current view at the current scale go first. `downloadView` fixes its set at the call. On-demand, from looking around, queues only missing Kacheln of the current view at the current scale. Closing drops both fills and in-flight fetches, and opening does not restore them. Going offline aborts the in-flight Kachel and keeps the unfinished fills; coming back online continues them. No fetch runs while offline or while the app is closed. `deleteCache` removes every Kachel, aborts in-flight fetches, drops the visit fills, and does not itself start a fetch. It leaves `ziele` and `downloadKnopf`. Remembered state is `{ ziele, downloadKnopf }`. A previous value that only holds heruntergeladen names is read as no Ziele and the checkbox off. The Standort is not stored. - The session exposes the Ziele newest first. Each Ziel carries its Koordinate and, when a Standort is known, its Entfernung in the existing German form (`500 m`, `1,5 km`). There is no single Ziel and no single Entfernung. There is no center-on-Ziel for "the" Ziel. Centering a particular Ziel and centering the Standort are separate requests. Both use 1:25,000. - Entering a Koordinate adds a Ziel when the text is valid, a Blatt covers the point, and that Koordinate is not already a Ziel. The same rules as before decide what is valid: Gitter case and spacing, exactly five digits, a real MGRS pair, and Blatt coverage. A rejection explains itself in German and changes nothing else. A success centers the view even when the Kacheln are blank, and the typed fields stay as entered. - Two Koordinaten are the same Ziel when the normalized Gitter, Rechtswert, and Hochwert match. The list stores that canonical Koordinate. - A tap is a ground point plus the current scale. Near means within 44 screen pixels, converted with the current metres-per-pixel. The nearest Ziel inside that radius is deleted. A tie deletes the newer Ziel. A tap with no Ziel inside the radius adds a Ziel at the metre of that point, using the same Blatt check and the same uniqueness rule, and does not move the view. The Standort is not a Ziel, so a tap on it adds one when the radius is empty. - Deleting a Ziel from the list does not move the view and does not ask. The screen's row control is labelled Löschen. - Ziele and the Download-Knopf checkbox are stored on the device with the other remembered session state. The heruntergeladen names are not stored. A stored list from a previous version that only holds those names is read as no Ziele and the checkbox off. Leaving the session and opening another one with the same storage brings the Ziele and the checkbox back. The Standort is not stored. - The first Standort after opening still centers the view once, and only when the person has not panned and has not added a Ziel since opening. Later Standorte update marks and Entfernungen only. - Hessen herunterladen asks the session to fetch every missing Kachel of Hessen. The view control asks it to fetch every missing Kachel that intersects the view at that moment, at every prepared scale. Both share one queue. Kacheln of the current scale of the current view are fetched before the rest. A second request of the same kind, while that request is still unfinished, does not add Kacheln. Pressing the other control does add its missing Kacheln, with the current scale still first. - The session reports the Hessen Kacheln already in the Cache and how many Hessen Kacheln exist, and the arrived and total counts of the Kacheln requested during this visit. The screen paints Hessen herunterladen red while any Hessen Kachel is missing, and disabled when none are. The red is the same red as a Ziel. While a visit request is unfinished, Einstellungen shows those arrived and total counts. After the app is closed, that visit request is gone, so opening shows no leftover progress. - Fetches run only while the session is told that the app is open and the device is online. Closing aborts the visit request and does not restore it on open. Going offline aborts the in-flight Kachel and keeps the visit request. Coming back online, still in that visit, continues it. Looking around still queues only missing Kacheln of the current view at the current scale. - Deleting the Cache removes every Kachel and does not start a fetch. It leaves Ziele and the checkbox. The screen still asks "Den ganzen Cache löschen?" before it tells the session to delete. There is no remove-Hessen request. Tests drive the session after that confirmation. - Einstellungen is the collapsed section that used to be Cache. Its header control is labelled Einstellungen. Ziele is the open section that used to be the Koordinate fields; its header control reads Ziele when collapsed and Einklappen when open. It keeps Auf Standort. The download control on the Karte is labelled Diese Ansicht herunterladen, sits at the bottom right, and is shown only when the checkbox is on. While `visit` is set, Einstellungen shows `Kacheln: ${arrived} von ${total}`. Hessen herunterladen uses the Ziel red while `hessen.arrived` is below `hessen.total`, and is disabled when they are equal. ## Testing Decisions - A good test drives the Karte session the way the screen will, and asserts what the screen would show. It does not assert how a Kachel is stored, how a library is called, or how a map is drawn. - The only module under test is the Karte session, the same seam as the first version. Tests supply a fake Übersicht, a fake Cache, a fake store for remembered state, and Standort, online, and app-open reports. They do not open a browser. - Cover several Ziele, order, uniqueness, both refusals, persistence across two sessions, Entfernung per Ziel and its absence, centering from an added Koordinate and from a chosen Ziel, tap-to-delete and tap-to-add including the 44 px radius and a point no Blatt covers, Hessen completeness without a stored mark, view-fill extent and scale, view-first queue order, a second press of the same request, pause on offline and stop on close without resume, on-demand limited to the current scale, and Cache deletion leaving Ziele and the checkbox. - The German confirmation for the Cache, the red and disabled painting, and the placement of the download control are screen copy and layout. They are not a second test seam. ## Out of Scope - Removing Hessen, or any other Gebiet, as its own action. - Remembering that a Gebiet was chosen, and continuing a fill merely because the app opened. - A stored name for the view that was fetched. The view is the set of Kacheln chosen at the press. - Deleting every Ziel in one action. - Changing how a Koordinate is parsed, how the Standort is obtained, the blue Standort, north-up, the 1:25,000 center, or the 36 km and 1.25 m zoom limits. - Routing, a typed Standort, and a Standort kept while the app is closed. ## Further Notes - Where the first-version spec still says there is one Ziel, that a Ziel is dropped on leave, that Hessen is marked heruntergeladen, that opening the app continues a fill, or that Hessen can be removed on its own, this spec replaces it. - The sample Koordinate `32U MA 67030 78109` is still a covered point. A second Ziel needs a different Koordinate the Übersicht also covers.