Skip to content

Quest: How much do you have to pay to use this parking spot?#6653

Open
marekkrug wants to merge 84 commits intostreetcomplete:masterfrom
marekkrug:master
Open

Quest: How much do you have to pay to use this parking spot?#6653
marekkrug wants to merge 84 commits intostreetcomplete:masterfrom
marekkrug:master

Conversation

@marekkrug
Copy link
Copy Markdown

This PR is a new Quest with the name "How much do you have to pay to use this parking spot?" and was described in the Issue #6651.

Copy link
Copy Markdown
Collaborator

@paulklie paulklie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great work so far, here are some ideas / topics for discussion

Copy link
Copy Markdown
Member

@westnordost westnordost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding UI design, I'd somewhat prefer a UI like this

[        ] EUR / [ hour ▼ ]

The currency simply being a text (unless there are actually several currency in use in a country??).
(Bonus: It would be nice if not the ISO currency id was used in display, but the actual currency symbol, e.g. €, $, £, ...)

The amount, being a decimal input field, you can use the generic composable I created de.westnordost.streetcomplete.ui.common.input.DecimalInput which handles decimal points locale-aware. I guess allowed would be at most 2 decimal digits?

Finally, in the issue it came up that actual pricing may vary depending on a number of factors which may confuse the user what to answer. An example from the discussion on the wiki page:

  • 1st hour: 2$ / hour
  • subsequent hours: 1$ / hour

Is there a reasonable hint text that could be added to explain what the user should answer in this case?

@westnordost
Copy link
Copy Markdown
Member

Also, I supposed specifically for this quest, it would make sense to always add check_date:charge=<date> because this information tends to be so volatile. If I remember correctly, we do the same for opening hours.

@marekkrug
Copy link
Copy Markdown
Author

Also, the dropdown for duration unit, I added

https://github.com/streetcomplete/StreetComplete/pull/6691/changes#diff-5fcb8673a43b9e77b5d7bb3a8868616fb209fbf57d361a9b5bb818759b316520

Maybe you should base your PR on top of that PR (or wait until that is merged) so that you can just reuse that widget.

I've rebased the project to that branch and tried to use the DurationUnitDropdown. The problem is that all the values there are in plural ("hours", "minutes", "days"), but in OSM you need "hour", "minute", "day" and probably "night" and "day" in the Future (https://wiki.openstreetmap.org/wiki/Key:charge#Usage) 🤔

@FloEdelmann FloEdelmann changed the base branch from master to opening_hours January 30, 2026 19:12
@westnordost
Copy link
Copy Markdown
Member

westnordost commented Jan 30, 2026 via email

@marekkrug
Copy link
Copy Markdown
Author

writing 2.00 USD/hours would be a bit weird in my opinion, in the wiki, the correct way to write it is 2.00 USD/hour...

@westnordost
Copy link
Copy Markdown
Member

westnordost commented Jan 31, 2026 via email

@FloEdelmann FloEdelmann deleted the branch streetcomplete:master February 1, 2026 22:09
@FloEdelmann FloEdelmann closed this Feb 1, 2026
@FloEdelmann

This comment was marked as resolved.

@westnordost westnordost reopened this Feb 5, 2026
@westnordost

This comment was marked as resolved.

@FloEdelmann FloEdelmann changed the base branch from opening_hours to master February 5, 2026 08:44
@FloEdelmann

This comment was marked as resolved.

@paulklie paulklie added the new quest accepted new quest proposal (if marked as blocked, it may require upstream work first) label Feb 11, 2026
@marekkrug
Copy link
Copy Markdown
Author

The quest is now running and working as far as I can see.

Are there any more problems that need to be fixed in this quest? Otherwise, it would be fine for me if it was merged in this state and to later add quests like "How much do you have to pay to use this toilet?" or similar in a seperate merge request :)

@westnordost
Copy link
Copy Markdown
Member

I haven't been following this PR lately. Are all the previous comments resolved? As a PR author, you can tap that button yourself.

@marekkrug
Copy link
Copy Markdown
Author

I read through them and resolved a lot of them. Looks like there's nothing really remaining other than potential other quests.

@westnordost
Copy link
Copy Markdown
Member

Alright, I will do a final review soon

@westnordost westnordost self-assigned this Feb 19, 2026
Copy link
Copy Markdown
Member

@westnordost westnordost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Phew, I am sorry to say this, but the currency formatter stuff is quite bonkers.

Each only in parts:

  • the formatting is all over the place and there is commented out stuff plus open TODO comments left
  • the doc comments make no sense
  • the iOS implementation at least again in parts can not work. E.g. getCurrencyCodeFromLocale just completely ignores the passed parameter and looks like you copy-pasted the code from the other method
  • the API of CurrencyFormatter (again, as for every point here in parts) make no sense (why is getCurrencyCodeFromLocale a method of an instance of CurrencyFormatter, what does the class have to do with a currency code?)
  • the tests for CurrencyFormatter only test half of the interface
  • the implementation of CurrencyFormatter on both platforms is over-complex and also wrong. The parameter is a country code and you search through all available locales to find the first locale that uses the currency of the country with the given code in order to format it (because you need a locale to format). Now, imagine the Euro is used in a country where one formats currency like this "1.500,00 €" (France) and in another country like this "€ 1 500.00" (Ireland). Oopsie! So, always the Locale (with region) must be passed to CurrencyFormatter.
  • the second static function of CurrencyFormatElements looks like it is completely copy-paste from the other one, plus, only one of these is used (outside tests) anyway! Funnily enough, the one that is not tested is the one that is actually used, while the one that is tested is not used in production 🤦
  • well, maybe more things, I lost the overview

I reckon that at least parts of this confusion might have been introduced as misunderstandings due to my requests to change your initial implementation of this, of course.
And since I looked into this code so deeply already, it makes sense if I rewrite that part myself rather than play PR ping pong. So, that's what I will do, you don't need to worry about this part.


The other parts I only skimmed through, but nevertheless I found some stuff. First and foremost, please make sure that you review your own code, too. I notice there are some TODOs and similar comments as well as sections of leftover commented out code.

For the other stuff, see below. Note however that this was just from skimming through it, there might be more in the details.

Comment on lines +7 to +11
val amount: String,
// e.g. "EUR"
val currency: String,
// either "day", "hour" or "minute"
val timeUnit: String
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless there is a good reason not to do that, at least amount should be a Double, timeUnitshould be aTimeUnit`.

)
}

TextField(
Copy link
Copy Markdown
Member

@westnordost westnordost Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use DecimalInput. This handles the locale aware decimal separator for you, as well as lets you set the maximum number of decimal places, plus the keyboard configuration.

Comment on lines +100 to +104
val timeUnit = when (durationUnitState.value) { // TODO: This could be removed if DurationUnit implements toOSMValue().
DurationUnit.HOURS -> "hour"
DurationUnit.DAYS -> "day"
DurationUnit.MINUTES -> "minute"
}
Copy link
Copy Markdown
Member

@westnordost westnordost Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create an extension function or add a method to DurationUnit, for example either parametrize the existing toOsmValue function to e.g. toOsmValue(alwaysUseSingular: Boolean = false) or add toOsmValueSingular function

Comment on lines +117 to +121
fun DurationUnit.getDisplayName(form: AddParkingChargeForm): String = when (this) {
DurationUnit.HOURS -> form.getString(R.string.quest_parking_charge_hour)
DurationUnit.DAYS -> form.getString(R.string.quest_parking_charge_day)
DurationUnit.MINUTES -> form.getString(R.string.quest_parking_charge_minute_short)
}
Copy link
Copy Markdown
Member

@westnordost westnordost Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have a look at how the string resource is created for other quests / composable UI. Could also use the DurationUnitDropdown but add a parameter that decides whether the unit should be written always in singular or not (analogous to my comment above)

@westnordost westnordost removed their assignment Feb 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new quest accepted new quest proposal (if marked as blocked, it may require upstream work first)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants