ATBUpdateTool/documentation/atb-update-tool.tex
2025-02-21 12:32:51 +01:00

3148 lines
95 KiB
TeX
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

\documentclass[fontsize=11
pt,a4paper,draft]{scrartcl}[2003/01/01]
\usepackage[english]{babel}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{textcomp}
\usepackage{blindtext}
\usepackage{mathpazo}
\usepackage{amsmath}
\usepackage{listings}
\usepackage{minted}
\usepackage{setspace}
\usepackage[acronym]{glossaries}
\usepackage{euler}
\usepackage[]{mdframed}
\usepackage{tabularx}
\usepackage{hyperref}
\usepackage{pifont}
\usepackage{float}
\usepackage{multirow}
\usepackage{uml}
\usepackage{tikz,pgfplots}
\usetikzlibrary{math}
\global\mdfdefinestyle{default}{%
linecolor=black,linewidth=1pt,%
innertopmargin=20,innerbottommargin=20
}
\lstset{emph={any-of,all-off},emphstyle=\textbf}
\title{Tariff File Structure}
%\author{Gerhard Hoffmann}
\date{\today\\\normalsize Version 0.8.0}
\newacronym{pnd}{PND}{\textbf{p}ay \textbf{and} \textbf{d}isplay machine}
\newacronym{psa}{PSA}{pay and display machine}
\newglossaryentry{customer}{
name=customer,
description={is either an operator of PND machines or a person buying
tickets using a PND.
Usually, it will be clear from the context, what kind of customer is meant}
}
\newglossaryentry{short-term-parking}{
name=short-term-parking,
description={mode for buying tickets using a PND.
Several tariff-steps are used to compute parking-price and
parking-time}
}
\newglossaryentry{tariff-file}{
name=tariff-file,
description={is a JSON formatted file defining a tariff and controlling
the tariff calculator for a certain product}
}
\newglossaryentry{tariff-calculator}{%
name=tariff-calculator,
description={%
software module implemented as a shared library.
Responsible to compute for parking times corresponding prices and
vice versa}%
}%
\newglossaryentry{tariff-step}{
name=tariff-step,
description={a step during the flow of a selling process.
Also known as time-step
Minimal duration: 1 minute.
}%
}
\newglossaryentry{prepaid tariff-step}{
name=prepaid tariff-step,
description={buy a product before
actual service tariff-step}
}
\newglossaryentry{prepaid-setting}{%
name=prepaid-setting,
description={settings for a prepaid tariff-step}
}%
\newglossaryentry{service time}{
name=service time,
description={union of all possible service tariff-steps}
}
\newglossaryentry{service tariff-step}{
name=service tariff-step,
description={tariff-step to buy products.
Possibly follows some prepaid and/or carry-over tariff-steps}
}
\newglossaryentry{carry-over tariff-step}{
name=carry-over tariff-step,
description={if carry-over setting is on, transition to next available
service tariff-step.
Otherwise, if carry-over setting is off, equals out-of-service tariff-step}
}
\newglossaryentry{carry-over time-step}{
name=carry-over time-step,
description={tariff-step within it is not possible to buy products.
If carry-over is off, identical to out-of-service tariff-step range}
}
\newglossaryentry{out-of-service tariff-step}{
name=out-of-service tariff-step,
description={tariff-step within it is not possible to buy products.
Opposite of service tariff-step.
If carry-over is on, identical to carry-over tariff-step}
}
\newglossaryentry{payment-setting}{
name=payment-setting,
description={include min-time, max-time, min-price, max-price}
}
\newglossaryentry{prepaid-if}{
name=prepaid-if,
description={conditions for prepaid}
}
\newglossaryentry{carry-over-if}{
name=carry-over-if,
description={conditions for carry-over}
}
\newglossaryentry{carry-over}{
name=carry-over,
description={boolean flag. Defined implicitly. True if carry-over
tariff-steps are defined,
false otherwise}
}%
\newglossaryentry{prepaid}{
name=prepaid,
description={boolean flag. Defined implicitly. True if prepaid tariff-steps
are defined,
otherwise false}
}
\newglossaryentry{time range}{
name=time range,
description={intervals of minutes. Minimal length: 1 minute. Written as
closed intervals. Right value does not belong to interval. Tariff-steps have
time ranges.
Example: [08:00 - 20:00]. Timepoint 20:00 does not belong to time range}
}%
\newglossaryentry{arrival-time}{%
name=arrival-time,
description={Time point of a customer's arrival at a \gls{pnd}.
Possibly different from start-time in case prepaid is set}
}%
\newglossaryentry{start-time}{%
name=start-time,
description={Time point of a customer's start of a selling process
at a \gls{pnd}}
}%
\newglossaryentry{wallclock-arrival-time}{
name=wallclock-arrival-time,
description={Time point of a customer's arrival at a \gls{pnd}, expressed as
wallclock time}
}%
\newglossaryentry{exit-time}{
name=exit-time,
description={Time point of a customer's leave at a PND}
}
\newglossaryentry{net-parking-time}{
name=net-parking-time,
description={charged part of the gross-parking-time}
}
\newglossaryentry{current-wallclock-parking-time}{
name=current-wallclock-parking-time,
description={current time point of selling process, expressed as wallclock
time}
}
\newglossaryentry{gross-parking-time}{
name=gross-parking-time,
description={complete parking time, including net-parking-time,
possible prepaid tariff-steps and carry-over tariff-steps.
Expressed i minutes. Also known as pre-tax-parking-time}
}
\newglossaryentry{product}{
name=product,
description={sold by a PND-machine. Possible values include:
usual parking ticket SHORT\_TERM\_PARKING}
}
\newglossaryentry{interpolate-last-tariff-step}{
name=interpolate-last-tariff-step,
description={termination mode for tariff-calculator. compute fractional
price for tariff-step on per minute basis}
}
\newglossaryentry{customer-overpay}{
name=customer-overpay,
description={termination mode for tariff-calculator. customer overpays,
but receives an replacement voucher to reclaim the overpaid amount}
}
\newglossaryentry{customer-unfairness}{
name=customer-unfairness,
description={termination mode for tariff-calculator. customer has to pay for
the complete last tariff-step}
}
\newglossaryentry{customer-fairness}{
name=customer-fairness,
description={termination mode for tariff-calculator. customer has not to pay
for
the last tariff-step}
}
\newglossaryentry{end-of-last-tariff-step}{
name=end-of-last-tariff-step,
description={termination mode for tariff-calculator. end of
the last tariff-step is the termination time-point}
}
\newglossaryentry{end-of-unique-tariff-step}{
name=end-of-unique-tariff-step,
description={termination mode for tariff-calculator. end of
unique tariff-step (e.g. day-ticket) is the termination time-point}
}
\newglossaryentry{tariff-step single}{
name=single,
description={tariff-step is not followed by other tariff-steps}
}
\newglossaryentry{cond}{
name=cond,
description={conditional modelling sequence of if, else if, else if, \dots,
else}
}
\newglossaryentry{allof}{
name=all-of,
description={synonym for a conventional \textbf(and) }
}
\newglossaryentry{anyof}{
name=any-of,
description={synonym for a conventional \textbf(or) }
}
\newglossaryentry{direct-coin-insertion}{
name=direct coin insertion,
description={preselection of parking-price or
parking-time by direct insertion of coins \textbf{only} }
}
\newglossaryentry{pre-selection}{
name=preselection,
description={preselection of parking-price or
parking-time using the GUI of a \gls{pnd}}
}
\newglossaryentry{overpay}{
name=overpay,
description={customer insert coins with an amount higher than actual ticket
price}
}
\newglossaryentry{missing-receipt-declaration}{
name=missing receipt declaration,
description={a \gls{pnd} could not return change, but a document a customer
can use to get the remaining money back}
}
\makeglossaries
\begin{document}
\maketitle
\tableofcontents
\section*{History}
\begin{table}[htbp]
\centering
\begin{tabularx}{\textwidth}{|>{\hsize=.15\hsize}c|>{\hsize=.25\hsize}X|>{\hsize
=.6\hsize}X|}
\hline
\textbf{Version} & \textbf{Date} & \textbf{Comment} \\
\hline
0.8.0 & \today & \\ \hline
\end{tabularx}
\end{table}
\pagebreak
\section{Introduction}
\subsection[Some background about the tariff calculation]{
Some background about the tariff calculation}
\subsubsection[Conceptual view]{Conceptual view}
If a customer wants to buy a ticket at a usual \gls{pnd}, there are
several options available:
\paragraph{
Pay with coins
}
The first option is \textbf{\gls{direct-coin-insertion}}. A
customer inserts coins, and the \gls{tariff-calculator} computes the
corresponding parking-price resp. parking-time on the fly while coins are
inserted.
The other option is \textbf{\gls{pre-selection}}. Using
Plus/Minus-buttons, a customer is displayed the current parking-time resp.
parking-price (again computed by the \gls{tariff-calculator} on the fly). In
case the customer doesn't have the matching coins available, he might be asked
for \textbf{\gls{overpay}}:
If the \gls{pnd} is equipped with a money changer and the customer confirms the
\gls{overpay} and the money changer can return the change, there will be no
problem. Otherwise, the customer will receive a
\gls{missing-receipt-declaration} to be able to collect the drawback. If the
customer denies the \gls{overpay}, the money will be returned.
If the \gls{pnd} is not equipped with a money changer, and the customer still
confirms, then the money will be lost.
\paragraph{
Pay with credit card
}
In this case the customer always uses \gls{pre-selection}. Using
Plus/Minus-buttons of the \gls{pnd}-display,
the customer chooses parking-time/-price (computed by the
\gls{tariff-calculator} on the fly) and buys the ticket
using a built-in credit-card terminal.
\paragraph{}
The tariff-calculation is controlled by two different main settings:
\begin{enumerate}
\item \textbf{Service time ranges}, usually given as fixed wall clock time
ranges.
For instance, a possible setting might be $08:00 20:00$, on every day
during a week. Other such time ranges are for instance
\textbf{carry-over} time ranges or \textbf{prepaid} time ranges.
\item The operator of some \gls{pnd}-machine may decide that the customer
has to pay in
\gls{tariff-step}s of 60 minutes per step.
Such 60 minute intervals are usually intertwined with the fixed service
time ranges.
The \gls{tariff-file} must contain settings which allow the calculation
to cope with such a requirement.
\end{enumerate}
To configure the behaviour of the \gls{tariff-calculator}, a so-called
\gls{tariff-file} is used.
It has the follwing properties:
%\begin{mdframed}[style=exampledefault]%
\begin{enumerate}
\item For historical reasons, its syntax is
\href{https://www.json.org/json-en.html}{JSON}.
\item It is generated using an external tool (tariff editor) (Audivo).
\item \Gls{tariff-file}s are kept in customer-specific git repositories.
\end{enumerate}
%\end{mdframed}
The \gls{tariff-calculator} uses a \gls{tariff-file} in a two-step process:
First, parse the \gls{tariff-file} into internal C/C++ data structures.
Then, using these structures, generate a sequence of \gls{tariff-step}s,
which are used as internal representation of the flow of a selling process.
\newline
\par{
This document defines the structure of a \gls{tariff-file} in an
incremental way. After the description of some settings,
there will be an example of mapping a tariff provided by some
\gls{pnd}-operator into a \gls{tariff-file} using these settings.
At the end of this document, several complete examples will be given.
}
\newline
\par{
Each day of the week is divided in \gls{service tariff-step}s (complementary
in \gls{out-of-service tariff-step}s).
There can be several of them for each day.
}
\newline
\par{
By definition, it is not possible to buy products during \gls{out-of-service
tariff-step}s. There are two exceptions to this rule: the special
\gls{out-of-service tariff-step}s \textbf{\gls{prepaid}} and
\textbf{carry-over} tariff-steps. \Gls{prepaid tariff-step}s allow to buy
products before actual \gls{service tariff-step}s whereas
\gls{carry-over tariff-step}s allow the transition to the next available
\gls{service tariff-step}.
}
\Gls{prepaid tariff-step}s can occur only at the beginning of a selling process,
whereas \gls{carry-over tariff-step}s can occur more often between
\gls{service tariff-step}s.
\subsubsection[Example]{%
Example}
Let carry\_over $($co$)$ and prepaid $($pp$)$ be set.
\begin{table}[h!]
\begin{center}
\label{tab:table1}
\begin{tabular}{|c|c|c|c|c|}
\hline
\textbf{00:00 - 08:00} & \textbf{08:00 - 12:00} & \textbf{12:00 - 14:00}
&
\textbf{14:00 - 20:00} & \textbf{20:00 - 24:00}\\
\hline
co / pp & service & co / pp & service & co / pp\\
\hline
\end{tabular}
\end{center}
\end{table}
If a customer arrives at 07:00, then the \gls{prepaid tariff-step} is
07:00-08:00
and the actual parking time starts at 08:00.
The next \gls{carry-over tariff-step} is from 12:00 14:00.
The customer does not have to pay for the \gls{prepaid tariff-step}.
\subsubsection[A more technical view]{A more technical view}
The steps of a tariff are represented as step-function. The discrete
values of the step-function are the prices of the various
\gls{tariff-step}s. The \gls{tariff-calculator} integrates this
step-function over the \gls{tariff-step}s (see figure below).
\begin{figure}[!h]
\begin{center}
\caption{Tariff as step-function}
\vspace{0.5cm}
\begin{tikzpicture}[scale=0.8]
% Definitions
\tikzmath{
\r0 = 0;
\r1 = 0.2;
\r2 = 0.3;
\r3 = 0.4;
\r4 = 0.1;
\r5 = 0.6;
\r6 = 0.5;
\t0 = 1;
\t1 = 2;
\t2 = 6;
\t3 = 10;
\t4 = 11;
\t5 = 12;
\t6 = 13;
\x0 = \t0; \y0 = \r0;
\x1 = \t1; \y1 = \r1;
\x2 = \t2; \y2 = \r2;
\x3 = \t3; \y3 = \r3;
\x4 = \t4; \y4 = \r4;
\x5 = \t5; \y5 = \r5;
\x6 = \t6; \y6 = \r6;
}
% Axis
\begin{axis}[
axis x line=middle,
axis y line=middle,
ylabel=Price,
%xlabel style={at={(10,10)},above right,yshift=10pt},
%xlabel style={at={(axis description cs:0.5,-0.1)},anchor=east},
%xlabel=Time,
xtick={0,\x0,\x1,\x2,\x3,\x4,\x5,\x6},
xticklabels={0,$t_0$,$t_1$, $t_2$, $t_3$,$t_4$,$t_5$,$t_6$,{ }},
xlabel near ticks,
extra x ticks={2, 6, 10, 14},
extra x tick labels={$08:00$,$09:00$,$10:00$,$11:00$},
extra x tick style={yshift={-30.0}},
ytick={0,\y0,\y1,\y2,\y3,\y5,\y6},
yticklabels={0,$p_0$,$p_1$, $p_2$, $p_3$,$p_5$,$p_4$},
ylabel near ticks,
xmax=\x6+2,
ymax=\y5+0.1,
xmin=0,
ymin=0
]
% Plots
%\addplot[domain=0:\t1] {\r1*x};
%\addplot[domain=\t1:\t2] {\r2*x};
%\addplot[domain=\t2:\t3] {\r3*x};
\draw[ultra thick] (axis cs:\x0,\y0) -- (axis cs:\x1, \y0);
\draw[thick] (axis cs:\x1,\y1) -- (axis cs:\x2, \y1);
\draw[ultra thick] (axis cs:\x2,0) -- (axis cs:\x3, 0);
\draw[thick] (axis cs:\x3,\y3) -- (axis cs:\x4, \y3);
\draw[ultra thick] (axis cs:\x4,\y5) -- (axis cs:\x5, \y5);
\draw[ultra thick] (axis cs:\x5,\y6) -- (axis cs:\x6, \y6);
\draw[dotted] (axis cs:\x1,0) -- (axis cs:\x1, \y1);
\draw[dotted] (axis cs:\x2,\y1) -- (axis cs:\x2, 0);
\draw[dotted] (axis cs:\x3,0) -- (axis cs:\x3, \y3);
\draw[dotted] (axis cs:\x4,\y3) -- (axis cs:\x4, \y5);
\draw[dotted] (axis cs:\x5,\y5) -- (axis cs:\x5, \y6);
\addplot[fill=white,only marks,mark=*]
coordinates{(\x1,\y0)(\x2,\y1)(\x3,0)(\x4,\y3)(\x5,\y5)(\x6,\y6)};
\end{axis}
\end{tikzpicture}
\end{center}
\end{figure}
\begin{enumerate}
\item The \gls{tariff-step} $[t_{0}, t_{1}]$ is a prepaid step having a
price of $0$ by definition. \Gls{arrival-time} is $t_0$, \gls{start-time}
is $t_1$. The price for the first \gls{tariff-step} is $p_1$ and its
duration is $60$ minutes.
\item The \gls{tariff-step} $[t_{2}, t_{3}]$ is a carry-over step;
price is $0$ as well, again by definition.
\item Note: \gls{tariff-step}s can have any price: they don't have to be
equal, increasing or decreasing. Additionally, they don't have to have the same
duration (i.e. length). The minimal duration of the various \gls{tariff-step}s
is one minute (for any possible tariff):
\[
\mid t_{i} - t_{j} \mid \; \geq 1
\]
for the time points $t_i$ above. The maximal duration is not limited,
but the typical maximal value is $24$ hours.
\end{enumerate}
\subsubsection[\Gls{tariff-step} notation]{%
\Gls{tariff-step} notation}
\Gls{tariff-step}s are written as closed intervals ($[00:00-08:00]$,
$[08:00-24:00]$, \dots).
Note that the time point $08:00$ is not included in the first interval.
Rather, it denotes the first minute of the interval $[08:00-24:00]$.
In the same manner $24:00$ denotes the first minute of the next day,
whereas $00:00$ denotes the first minute of the current day.
The same holds for intervals given in time point notation $[t_1,t_2]$
as above.
\subsubsection{%
Basic workflow of the tariff calculator}
The \gls{tariff-calculator} just integrates over the \gls{tariff-step}s.
The only exception is if a last \gls{tariff-step} has to be refined to a
higher (minute) resolution.
The effect of the Plus/Minus-buttons is basically to move the calculator
forward / backward by one step.
%Carry-over \gls{tariff-step}s or prepaid time ranges are not included
%in the step-function.
\subsubsection[Interpolation]{%
Interpolation
}
\paragraph{%
How to interpolate into \gls{tariff-step}s
}
It is quite common that all \gls{tariff-step}s have the same duration,
say $5$ minutes. Now, if \gls{service time} ends at $20:00$ and there is no
carry-over allowed, this raises a problem if the last \gls{tariff-step} ends
closer to $t = 20:00$ than $5$ minutes:
\[
\mid t_{last} - t \mid \; < 5
\]
What shall happen with these last minutes? Several options are possible:
% manchmal egal: bei tagesticket oder 24h-ticket
\paragraph{%
Use minute resolution
}
Compute the price for $1$ minute based on the price for the
last \gls{tariff-step}. If applicable, this resolves the issue.
But sometimes this option is not possible:
\paragraph{%
Rounding problems
}
This problem arises if the price of the last $5$ minutes from above is not a
multiple of $5$. Dividing by $5$ might result in a fractional, i.e. non-integer
value.
\paragraph{%
(Direct) coin insertion
}
In this case it might be possible to ask the customer for \gls{overpay}.
\paragraph{%
Preselection using Plus/Minus
}
Using the Plus/Minus-buttons a user can preselect parking-time and
parking-price. "Plus" means to go forward in time by a certain amount of
\gls{tariff-step}s, "Minus" means to go backward to the
previous \gls{tariff-step}.
Thus "Plus" allows to move forward much faster
than backward with "Minus". The reason is user convenience. As the customer
must be able to select any possible price, the backward move must have the
finest possible resolution.
TODO: configure forward step-size.
\subsection[Interface of the \gls{tariff-calculator}]{%
Interface of the tariff calculator}
\subsubsection{%
Dependency to existing software components}
The tariff-calculator is used by the main application ATBQT
with the help of a special wrapper around the actual tariff-calculator.
\begin{center}
\framebox[250pt][c]{ATBQT | Tariff Simulator | Tariff Editor }\\
\framebox[250pt][c]{wrapper for tariff-calculator (plugin)}\\
\framebox[250pt][c]{tariff-calculator (library)}
\end{center}
The \gls{tariff-calculator} is basically about computing two values:
\begin{enumerate}
\item Given \gls{net-parking-time}, compute the corresponding parking
price (any prepaid-/carry-over time ranges are excluded).
\item Given a price, compute the corresponding net- and
\gls{gross-parking-time}s.
\item Additionally, it has to return error states to the caller for
(direct) coin insertion: the customer might have inserted
an amount greater than the allowed max-price (error state overpaid).
\end{enumerate}
\subsubsection{%
C Interface of the tariff calculator (in progress)}
Although the \gls{tariff-calculator} is written in C\texttt{++}, there will
be a C interface to be used by external software written in a
different language like for instance C\texttt{\#}.
\paragraph{Tariff calculator}
\label{tariff-calculator-interface}
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{c}
TariffCalculator *allocTariffCalculator(char const *tariff_file);
// allocate tariff-calculator based on tariff-file.
// note that a tariff-file is for a single product:
// if there are several products to be handled
// at the same time, allocate multiple tariff-calculators.
freeTariffCalculator(TariffCalculator *tc);
// free a previously allocated tariff-calculator.
TariffCalculatorState *forward(TariffCalculator *tc);
// move the tc forward by a configured number of tariff-steps.
TariffCalculatorState *backward(TariffCalculator *tc);
// move the tc backward by one tariff-step.
TariffCalculatorState *currentState(TariffCalculator const *tc);
// get current state of the tariff-calculator.
TariffCalculatorState *priceGrossDTime(TariffCaculator const *tc,
char gross_datetime[]);
// compute price using tariff-calculator and gross_datetime,
// which is given in ISO-format: '2024-01-01T12:00:00'.
// Refer to TariffCalculatorState for possible result.
TariffCalculatorState *priceNetTime(TariffCaculator const *tc,
uint32_t net_parking_time);
// compute price using tariff-calculator and net_parking_time,
// given in minutes.
// Refer to TariffCalculatorState for possible result.
TariffCalculatorState *priceGrossTime(TariffCaculator const *tc,
uint32_t gross_parking_time);
// compute price using tariff-calculator and gross_parking_time,
// given in minutes.
// Refer to TariffCalculatorState for possible result.
TariffCalculatorState *timeForPrice(TariffCaculator const *tc,
unsigned int price);
// compute parking-time for given price.
// Refer to TariffCalculatorState for possible result.
};
\end{minted}
\paragraph{Tariff calculator state}
\label{tariff-calculator-state}
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{c}
typedef struct TimePoint {
char tp[20];
// time point given in ISO-format: '2024-01-01T12:00'
} TimePoint;
struct TariffCalculatorState {
char start[20];
// start time of the tariff-calculation, given
// in ISO-format: '2024-01-01T12:00'
unsigned int net_parking_time;
// net parking time so far, given in minutes
char net_parking_time_date[20];
// net parking time so far, given as date in
// ISO-format: '2024-01-01T12:00'
unsigned int gross_parking_time;
// net parking time so far, given in minutes
char gross_parking_time_date[20];
// net parking time so far, given as date in
// ISO-format: '2024-01-01T12:00' */
unsigned int price;
// price so far
};
\end{minted}
\subsection[Conditional Expressions in a Tariff File]{%
Conditional Expressions in a Tariff File}
Sometimes it is necessary to encode conditionals in JSON. Here the
following approach is used: assume for example some pseudo-code like this:
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{c}
(("A" < 10 && "B" > 100) || "C" == 0)
\end{minted}
\subsubsection[any-of and all-of]{%
any-of and all-of}
In order to model such an expression, use the conditionals
\textbf{\gls{anyof}} and \textbf{\gls{allof}}.
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
"any-of": [
{
"all-of": [
{ "A": { "lt": 10}},
{ "B": { "gt": 100}}
]
},
{
"C": { "eq": 0}
}
]
\end{minted}
"any-of" plays the role of the operator OR, whereas "all-of" is for modeling
the operator AND.
\subsubsection[cond]{%
\gls{cond}}
In order to model "if, else if, else if, \dots, else" use
\textbf{\gls{cond}}.
The objects of a \gls{cond}-array consist of two entries: the first one
is a test, the second line some kind of expression, typically just a
value.
If the test evaluates to true, then the evaluation of the expression
is returned, and \gls{cond} stops. Otherwise, then next object
is tried. If all tests fail, then there is an (optional) else-object
and its evaluation is returned. If there is no such an else-object, then
false will be returned.
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
"cond": [
{
"current-wallclock-parking-time": {
"<": "14:00",
"then": "14:00"
}
},
{
"current-wallclock-parking-time": {
"<": "18:00",
"then": "18:00"
}
},
{
"else": "24:00"
}
]
\end{minted}
\section{The header of the tariff file}
A tariff file starts with some general entries.
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"project": "project-name",
"version": "1.0.0",
"info": "",
"product": "short-term-parking"
}
\end{minted}
\begin{enumerate}
\item \textbf{project}
Optional. A string in free format describing the project. Typically
includes a location.
\item \textbf{version}
Optional. Version of the tariff file. Should follow Semantic
Versioning.
\item \textbf{info}
Optional. Free format string for own use.
\item \textbf{product}
Optional. A string describing the product in use for this tariff file.
Available products are:
\begin{enumerate}
\item short-term-parking
\item day-ticket
\item 24-h-ticket
\item \dots
\end{enumerate}
\Gls{product} is always implicitly defined, as there is exactly one
\gls{tariff-file} for each \gls{product}.
\end{enumerate}
Following the initial entries, the tariff file is divided in a top and bottom
half.
The top part includes general settings, which can be overwritten in the bottom
part on a per-day basis, which is similar to the inheritance
in object-oriented programming.
\section{The top half of the tariff file}
The top part consists of \textbf{payment-setting}, \textbf{prepaid settings},
\textbf{service settings} and \textbf{carry-over settings}. For example, a
payment-setting might be a simple as
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"payment-settings”: [
{
"min-time": 30,
"max-time": 840,
"min-price": 50,
"max-price": 1400,
"allow-overpay": true
}
]
}
\end{minted}
\subsection{payment-settings}
Defines the general settings for a buying a \gls{product}.
\begin{enumerate}
\item \textbf{min-time}:
Mandatory. Minimal parking time. Never bigger than maximal parking
time.\\
Possible values:
\begin{enumerate}
\item a non-negative integer: minimal parking time in minutes.
\item string (format "h:m"): e.g. "$24:00$": minimal parking time is
supposed to last until $24:00$ (next midnight).
\item settable using \textbf{cond}-conditional.
Example: If \gls{current-wallclock-parking-time} is before $14:00$,
then min-time is until $14:00$. Otherwise it is $24:00$
(next midnight).
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"min-time": {
"cond": [
{
"current-wallclock-parking-time": {
"<": "14:00",
"then": "14:00"
}
},
{
"else": "24:00"
}
]
}
}
\end{minted}
\end{enumerate}
\item \textbf{max-time}:
Maximal parking time. Never smaller than minimal parking time.
Possible values:
\begin{enumerate}
\item a non-negative integer: maximal parking time in minutes.
\item string (format "h:m"): e.g. "$24:00$" maximal parking time is
supposed to last until $24:00$ (next midnight).
\item string: "unlimited".
\item settable using \textbf{cond}-conditional.
Example: If \gls{current-wallclock-parking-time} is before $14:00$,
then max-time is until $14:00$. Otherwise it is $24:00$
(next midnight).
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"max-time": {
"cond": [
{
"current-wallclock-parking-time": {
"<": "14:00",
"then": "14:00"
}
},
{
"else": "24:00"
}
]
}
}
\end{minted}
\end{enumerate}
\item \textbf{min-price:}
Mandatory. Minimal parking price. Never bigger than maximal parking
price.\\
\begin{enumerate}
\item a non-negative integer: minimal parking price.
\item settable using \textbf{cond}-conditional.
Example: If \gls{current-wallclock-parking-time} is before $14:00$,
then min-price is until $800$. Otherwise it is $500$.
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"min-price": {
"cond": [
{
"current-wallclock-parking-time": {
"<": "14:00",
"then": 800
}
},
{
"else": 500
}
]
}
}
\end{minted}
\end{enumerate}
\item \textbf{max-price}:
Mandatory. Maximal parking price.
\begin{enumerate}
\item a non-negative integer: maximal parking price.
\item settable using \textbf{cond}-conditional. See min-price.
\end{enumerate}
\item \textbf{price-scaling-factor}:
Scaling factor to prevent rounding errors.
\item \textbf{allow-overpay}:
Allow overpay, e.g. if the customer does not
have the coins to pay the exact price.
Possible values: true/false.
% \item \textbf{accumulate\_step\_prices}: If \textbf{true}, accumulate
% prices in payment rate (todo).
% \item \textbf{accumulate\_step\_durations}: If \textbf{true},
% accumulate durations in duration (todo).
\end{enumerate}
\subsubsection*{Implicit settings}
\begin{enumerate}
\item \textbf{carry\_over}:
If the selling process runs beyond a certain time point (usually
midnight),
then:
\begin{enumerate}
\item if \textbf{true}, continue tariff calculation with the current
price / parking time.
\item if \textbf{false}, stop tariff calculation. Return current
price
and parking time.
\end{enumerate}
\item \textbf{prepaid:} allow a customer to by a product before an actual
service time.
\begin{enumerate}
\item if \textbf{true}, continue tariff calculation with the next
possible \gls{start-time}.
\item if \textbf{false}, stop tariff calculation. Return error,
because inside \gls{out-of-service tariff-step} range.
\end{enumerate}
\end{enumerate}
\subsection{prepaid-settings}
“Prepaid” (“Vorkauf”) is a special operation mode, which makes it possible
to buy some product before service time.
There can be several \gls{prepaid tariff-step}s per day (depending on how
many \gls{service tariff-step}s exist).
\Gls{prepaid} is optional. If not given in the tariff file, no \gls{prepaid}
is possible, i.e. the implicit \gls{prepaid}-flag is not set.
\begin{enumerate}
\item \textbf{prepaid-ranges}
\begin{enumerate}
\item[] \textbf{prepaid-duration}: Conditional. If prepaid-start and
prepaid-end are given,
it can be computed.
\item[] \textbf{prepaid-start}: Mandatory. Start of prepaid time
range.
\item[] \textbf{prepaid-end}: Conditional. If prepaid-duration is
given, it can be computed.
\end{enumerate}
\end{enumerate}
\subsubsection*{Example}
A customer has an appointment with her doctor at 7:00,
and service time starts at 8:00. Parking is free before 8:00.
If the appointment would take more than one hour, then the customer
could not buy a parking-ticket before 8:00 without the prepaid-mode.
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-duration": 480,
"prepaid-start": "00:00",
"prepaid-end": "08:00"
},
{
"prepaid-duration": 240,
"prepaid-start": "20:00",
"prepaid-end": "24:00"
}
]
}
]
}
\end{minted}
\subsection{service-settings}
\Gls{service tariff-step}sare (in most cases) not free,
and there can be more than one such \gls{tariff-step} per day.
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"service-settings": [
{
"service-ranges": [
{
"service-duration": 720,
"service-start": "08:00",
"service-end": "20:00"
}
]
}
]
}
\end{minted}
\begin{enumerate}
\item \textbf{service-ranges}
\begin{enumerate}
\item[] \textbf{service-duration:} Conditional. If service-start and
service\_end are given,
it can be computed.
\item[] \textbf{service-start:} Mandatory. Start of \gls{service
tariff-step} range.
\item[] \textbf{service-end:} Conditional. If service-duration is
given, it can be computed.
\end{enumerate}
\end{enumerate}
\subsection{out-of-service-settings}
During \gls{out-of-service tariff-step} parking is forbidden.
The exception to this rule is in case the general
\textbf{carry\_over}-flag is true, where \gls{out-of-service tariff-step}s
are in fact \gls{carry-over tariff-step}s. Indeed, defining
\gls{carry-over tariff-step}s in the \gls{tariff-file} means
that the \gls{carry-over}-flag is implicitly defined. In such
a case, it is possible to jump across a \gls{carry-over tariff-step}
and and to continue with the next available \gls{service tariff-step}.
The same holds true for the textbf{prepaid}-flag and \gls{prepaid tariff-step}s.
\subsubsection*{Remark}
It might happen that all \gls{service tariff-step}s stretch always
full days. Hence, there are no \gls{out-of-service tariff-step}s
and no \gls{carry-over tariff-step}s: the \gls{carry-over}-flag is
implicitly set to \textbf{false} in this case, as there is no carry-over.
\subsection{tariff-steps}
One of the most important objects in the \gls{tariff-file}.
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"tariff-steps": [
{
}
]
}
\end{minted}
\begin{enumerate}
\item \textbf{\gls{tariff-step}s}
Some variables of a \gls{tariff-step} can be given statically,
i.e. at load-time of the \gls{tariff-file}. Others may be
set only at runtime as \textbf{step\_start} below.
Depending on the context, different values of a \gls{tariff-step}
will be defined.
\begin{enumerate}
\item[] \textbf{step-duration-in-minutes}: if defined, the
length of a \gls{tariff-step} in minutes.
\item[] \textbf{step-start:} may be set to
\begin{enumerate}
\item \textbf{anytime}: the \gls{tariff-step} starts at an
arbitrary time-point. Can only be set at runtime.
\item \textbf{now}: synonymous for \textbf{anytime}
\item explicitly given time-point as \textbf{12:00}
\end{enumerate}
\item[] \textbf{step-start-after:} explicitly given
time-point as \textbf{12:00}.
Take step into account if start of price calculation
is after this time-point.
\item[] \textbf{step-start-before:} explicitly given
time-point as \textbf{12:00}.
Take step into account if start of price calculation
is before this time-point.
\item[] \textbf{step-end:} may be set to
\begin{enumerate}
\item explicitly given time-point as \textbf{20:00}
\item \textbf{midnight}: the \gls{tariff-step} ends at midnight.
Same as time-point setting 24:00.
\end{enumerate}
\item[] \textbf{step-price-per-minute:} used for interpolating
the price of the \gls{tariff-step} in case the \gls{tariff-step}
is not fully used.
\item[] \textbf{step-price} full price of the \gls{tariff-step}.
\item[] \textbf{step-type} type of \gls{tariff-step}. Possible values:
\begin{enumerate}
\item \gls{tariff-step single}
\item cont
\end{enumerate}
\end{enumerate}
\end{enumerate}
\subsection{special days}
TODO.
Settings for public holidays and open for sale days
\subsection{carry-over-if}
TODO.
Basically describe under what conditions a carry-over
might take place.
\subsection{prepaid-if}
\subsection{Example: tariff file using top half}
The tariff is given by the PND-operator as follows:
\begin{enumerate}
\item 24/7 service time ranges for all parking machines on all weekdays.
\item No exceptions (for example for holidays).
\item Each weekday is handled the same way.
\item Customer can buy ticket valid for up to 7 days. For each began day,
the price is 7 euros.
\item Do not allow overpay: if the customer pays with coins, paying 51 euros
means 2 euros lost.
\end{enumerate}
These requirements mean that the maximal parking time is 7 days (or 10080
minutes), minimal price is 7 euros and maximal price is 49 euros. Further, there
is no prepaid and no carry-over (because 24/7 service time). Because the is
no difference between the weekdays, there is no need to override some settings
in a bottom half of the tariff file.
The mapping of the tariff to a JSON file results in:
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"project": "project-name",
"version": "1.0.0",
"product": "short-term-parking",
"payment-settings": {
"min-time": "24:00",
"max-time": 10080,
"min-price": 700,
"max-price": 4900,
"allow-overpay": false
},
"service-settings": {
"service-ranges": [
{
"service-start": "00:00",
"service-end": "24:00"
}
]
},
"tariff-steps": [
{
"step-start": "now",
"step-end": "24:00",
"step-price": 700,
"comment": "first tariff-step",
"comment": "customer can buy anytime (now)",
"comment": "step ends at midnight"
},
{
"step-duration": 1440,
"comment": "step-duration given for clarity",
"step-start": "00",
"step-end": "24:00",
"step-repetition-count": 6,
"step-price": 700,
"comment": "the following (max. 6) tariff-steps",
"comment": "price uniformly 7 euros for each day"
}
]
}
\end{minted}
\section{The bottom half of the tariff file}
The bottom part of the tariff file is for overriding the general settings in the
top half of the tariff file. For each week day,
settings can be overridden separately. If a day is not mentioned, the settings
from the top half apply.
The general layout of the bottom half therefore looks like this:
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"monday": [{
"default": {
}
}],
"tuesday": [{
"default": {
}
}],
"wednesday": [{
"default": {
}
}],
"thursday": [{
}],
"friday": [{
"default": {
}
}],
"saturday": [{
"default": {
}
}],
"sunday": [{
"default": {
}
}]
}
\end{minted}
Some days are special, though, for instance holidays or open for sale sundays.
They are mapped into their corresponding weekdays using their date.
Special days are handled with higher priority.
\subsection*{Example}
Christmas Day in 2024 will be at 2024-12-25, a Wednesday. The same holds for New
Years Day. This results in the following setting:
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"wednesday": [{
"2025-01-01": {
"comment": "New Years Day"
},
"2024-12-25": {
"comment": "Christmas Day"
},
"default": {
"comment": "usual wednesday"
}
}]
}
\end{minted}
\subsection{Example: tariff file using top and bottom half}
\label{top-and-bottom}
The tariff is given as follows:
\begin{enumerate}
\item Service time ranges: Monday Sunday: $08:00 18:00$.
\item Holidays are handled as Sundays.
\item The first $20$ minutes are free for each weekday.
\item Cost for every other $20$ minutes: $40$ cent.
\item Maximal parking time for Monday-Saturday: 1 hour. Cost: $80$ cent.
For Sunday: $3$ hours. Cost: $3,20$ euros.
\item Prepaid: Yes. No restriction on prepaid time ranges.
\item Carry-over: Yes.
\item Plus/Minus: step forward every $20$ minutes, step backward every $5$
minutes.
\item Service time restriction: carry-over from Sunday/Holiday to next day
results in service time range of $08:00-09:00$ on next day. Even if the next day
is a holiday.
\end{enumerate}
\paragraph{Note}
Due to this specification, $1$ minute costs $2$ cent. Thus, paying by
credit-card is not a problem. Because overpay is allowed, there is also no
problem for a
transition from Sunday to Monday when reaching $09:00$.
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"project": "project-name",
"version": "1.0.0",
"product": "short-term-parking",
"payment-settings": [
{
"min-time": 20,
"max-time": 60,
"min-price": 0,
"max-price": 80,
"allow-overpay": true
}
],
"service-settings": [
{
"service-ranges": [
{
"service-start": "08:00",
"service-end": "18:00"
}
]
}
],
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "08:00"
},
{
"prepaid-start": "18:00",
"prepaid-end": "24:00"
}
]
}
],
"carry-over-settings": [
"carry-over-if": {
"cond": [
{
"max-remaining-net-parking-time": {
"<=": 60,
"then": true
}
},
{
"max-remaining-parking-price": {
"<=": 120,
"then": true
}
},
{
"else": false
}
]
}
],
"tariff-steps": [
{
"step-start": "now",
"step-duration": 20,
"step-price": 0
},
{
"step-duration": 5,
"step-repetition-count": 32,
"step-price": 10,
"comment": "repetition count controlled by max-time"
}
],
...
"wednesday": [{
"2025-01-01": {
"comment": "New Years Day",
"type": "holiday",
"payment-settings": [
{
"min-time": 20,
"max-time": 180,
"min-price": 0,
"max-price": 320,
"allow-overpay": true
}
]
}
}]
...
}
\end{minted}
\section{Use Cases}
In this section, several complete examples will be listed.
\subsection{Prepaid. Carry over. Weekend free. Price scaling.}
\subsubsection{Szeged (Hungary)}
The tariff (for Zone 1) is given as follows (special days for 2024):
\begin{enumerate}
\item[$\bullet$] Service time ranges: Monday Friday: 08:00 18:00.
\item[$\bullet$] Saturday and Sunday and public holidays are free
except PND-operator says otherwise.
\item[$\bullet$] Special open for sale days during the year (e.g. Saturdays
which are not free).
\item[$\bullet$] Price per hour: 150 Forint.
\item[$\bullet$] Minimal parking time: 15 minutes.
\item[$\bullet$] Minimal parking price: 38 Forint.
\item[$\bullet$] Maximal parking time: 6 hours.
\item[$\bullet$] Maximal parking price: 900 Forint.
\item[$\bullet$] Prepaid: Yes. No restriction on \gls{prepaid
tariff-step}(s).
\item[$\bullet$] Carry-over: yes.
\item[$\bullet$] Interpolate: no.
\item[$\bullet$] Allow overpay: yes.
\end{enumerate}
\subsubsection*{Remark: price-scaling-factor}
The settings for Szeged shows that the price for 15 minutes is
\begin{equation*}
(150 / 60) * 15 = 2,5 * 15 = 37,5
\end{equation*}
possibly introducing rounding errors. To fix this problem, scale the
price setting such that the division by $60$ never produces some rest:
price-scaling-factor $= LCM(150, 60) / 150 = 300 / 150 = 2$
where $LCM(x,y)$ is the least common multiple of the integers $x, y$.
The price for 15 minutes is then internally
$37,5\; *$ price-scaling-factor $= 75$
and the computed price has to be divided by the price-scaling-factor
to get the correct result, of course.
\paragraph{Remark}
The smallest possible coin in Szeged is 5 Forint.
According to the scaled setting, 5 Forint (HUF) are exactly 1 minute
parking-time: $5 * 60 = 300$, the scaled price.
\paragraph{Remark}
Such a scaling would be possible for the time-dimension only for cases where
there is full service time (no carry over or prepaid). Usually the duration
must be computed for every \gls{tariff-step}, see section \ref{Stockerau}.
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"project": "Szeged",
"version": "1.0.0",
"product": "short-term-parking",
"payment-settings": [
{
"min-time": 15,
"max-time": 360,
"min-price": 75,
"max-price": 1800,
"comment": "prices already scaled",
"price-scaling-factor": 2,
"allow-overpay": true
}
],
"service-settings": [
{
"service-ranges": [
{
"service-start": "08:00",
"service-end": "18:00"
}
]
}
],
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "08:00"
},
{
"prepaid-start": "18:00",
"prepaid-end": "24:00"
}
]
}
],
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "00:00",
"carry-over-end": "08:00"
},
{
"carry-over-start": "18:00",
"carry-over-end": "24:00"
}
]
}
],
"tariff-steps": [
{
"step-start": "now",
"step-duration": 15,
"step-price": 75
},
{
"step-duration": 15,
"step-repetition-count": 23,
"step-price": 75,
"comment": "in total 345 minutes and cost 1725 HUF"
}
],
"monday": [{
"default": {
"comment": "settings from top half apply"
}
}],
"tuesday": [{
"default": {
"comment": "settings from top half apply"
}
}],
"wednesday": [{
"2024-12-25": {
"comment": "Christmas Day",
"comment": "Public Holidays are free",
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "24:00"
}
]
}
],
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "00:00",
"carry-over-end": "24:00"
}
]
}
]
},
"default": {
"comment": "settings from top half apply"
}
}],
"thursday": [{
"2024-12-26": {
"comment": "2nd day of Christmas",
"comment": "Public Holidays are free",
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "24:00"
}
]
}
],
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "00:00",
"carry-over-end": "24:00"
}
]
}
]
},
"default": {
"comment": "settings from top half apply"
}
}],
"friday": [{
"default": {
"comment": "settings from top half apply"
}
}],
"saturday": [{
"2024-12-07": {
"comment": "Open For Sale",
"comment": "settings from top half apply"
},
"default": {
"comment": "Saturday is free",
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "24:00"
}
]
}
],
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "00:00",
"carry-over-end": "24:00"
}
]
}
]
}
}],
"sunday": [{
"default": {
"comment": "Sunday is free",
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "24:00"
}
]
}
],
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "00:00",
"carry-over-end": "24:00"
}
]
}
]
}
}]
}
}
\end{minted}
\subsection{Full time service. No overpay.}
\subsubsection{Galtür}
\begin{enumerate}
\item[$\bullet$] Service time ranges: Monday Sunday: 00:00 24:00.
\item[$\bullet$] Price per day: 7 euros.
\item[$\bullet$] Minimal parking time: 1 day.
\item[$\bullet$] Minimal parking price: 7 euros.
\item[$\bullet$] Maximal parking time: 7 days.
\item[$\bullet$] Maximal parking price: 49 euros.
\item[$\bullet$] Allow overpay: no.
\item[$\bullet$] Prepaid: no.
\item[$\bullet$] Carry over: no.
\end{enumerate}
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"project": "Galtuer",
"version": "1.0.0",
"product": "short-term-parking",
"payment-settings": [
{
"min-time": "24:00",
"max-time": 10080,
"min-price": 700,
"max-price": 4900,
"allow-overpay": false
}
],
"service-settings": [
{
"service-ranges": [
{
"service-start": "00:00",
"service-end": "24:00"
}
]
}
],
"comment": "no prepaid-settings",
"comment": "no carry-over-settings",
"tariff-steps": [
{
"step-start": "now",
"step-end": "24:00",
"step-price": 700,
"comment": "first tariff-step",
"comment": "customer can buy anytime (now)",
"comment": "step ends at midnight (next day)"
},
{
"step-duration": 1440,
"comment": "step-duration given for clarity",
"step-start": "00:00",
"step-end": "24:00",
"step-repetition-count": 6,
"step-price": 700,
"comment": "the following (max. 6) tariff-steps",
"comment": "price uniformly 7 euros for each day"
}
],
"comment": "not mentioning monday-sunday means that",
"comment": "for monday-sunday apply settings from top-half",
"comment": "of tariff-file"
}
}
\end{minted}
\subsection{Decreasing price the later \gls{start-time}}
\subsubsection{Pernegg an der Mur}
\begin{enumerate}
\item[$\bullet$] Service time ranges: Monday Sunday: 06:00 17:00.
\item[$\bullet$] Product: day-ticket.
\item[$\bullet$] Price per day:
\begin{enumerate}
\item 2 euros if \gls{start-time} after $16:00$
\item 3 euros if \gls{start-time} after $15:00$
\item 3 euros if \gls{start-time} after $06:00$
\end{enumerate}
\item[$\bullet$] Minimal parking time: 60 minutes.
\item[$\bullet$] Minimal parking price: 2 euros.
\item[$\bullet$] Maximal parking time: 11 hours (660 minutes).
\item[$\bullet$] Maximal parking price: 6 euros.
\item[$\bullet$] No special days..
\item[$\bullet$] Allow overpay: no.
\item[$\bullet$] Carry over: no.
\item[$\bullet$] Prepaid: no.
\end{enumerate}
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"project": "Pernegg an der Mur",
"version": "1.0.0",
"product": "day-ticket",
"payment-settings": [
{
"min-time": "17:00",
"max-time": "17:00",
"min-price": 200,
"max-price": 600,
"allow-overpay": false
}
],
"service-settings": [
{
"service-ranges": [
{
"service-start": "06:00",
"service-end": "17:00"
}
]
}
],
"comment": "no prepaid-settings",
"comment": "no carry-over-settings",
"comment": "implicit out-of-service time",
"comment": "i.e. complement of service time",
"tariff-steps": [
{
"step-start-after": "06:00",
"step-start-before": "15:00",
"step-end": "17:00",
"step-price": 600,
"comment": "unique tariff-step"
},
{
"step-start-after": "15:00",
"step-start-before": "16:00",
"step-end": "17:00",
"step-price": 300,
"comment": "unique tariff-step"
},
{
"step-start-after": "16:00",
"step-end": "17:00",
"step-price": 200,
"comment": "unique tariff-step"
}
],
"comment": "not mentioning monday-sunday means that",
"comment": "for monday-sunday apply settings from top-half",
"comment": "of tariff-file"
}
}
\end{minted}
%\subsection{Linsinger Maschinenbau}
%\subsection{Nordisches Ausbildungszentrum (NAZ)}
\subsection{Full time service. Variable \gls{tariff-step}s.}
\subsubsection{Christoph Reisen}
\begin{enumerate}
\item[$\bullet$] Service time ranges: Monday Sunday: 00 24:00.
\item[$\bullet$] Prices:
\begin{enumerate}
\item 0-6 hours: 6 euros
\item 7 hours: 7 euros
\item 24 hours: 8 euros
\item 48 hours: 16 euros
\item 72 hours: 24 euros
\item 90 hours: 32 euros
\item 124 hours: 40 euros
\end{enumerate}
\item[$\bullet$] Minimal parking time: 360 minutes.
\item[$\bullet$] Minimal parking price: 6 euros.
\item[$\bullet$] Maximal parking time: $124 * 60 = 7440$ minutes.
\item[$\bullet$] Maximal parking price: 40 euros.
\item[$\bullet$] Allow overpay: yes.
\end{enumerate}
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"project": "Christoph Reisen",
"version": "1.0.0",
"product": "day-ticket",
"payment-settings": [
{
"min-time": 360,
"max-time": 7440,
"min-price": 600,
"max-price": 4000,
"price-scaling-factor": 1,
"allow-overpay": true
}
],
"service-settings": [
{
"service-ranges": [
{
"service-start": "00:00",
"service-end": "24:00"
}
]
}
],
"comment": "no prepaid-settings",
"comment": "no carry-over-settings",
"comment": "implicit out-of-service time",
"comment": "i.e. complement of service time",
"tariff-steps": [
{
"step-start": "now",
"step-duration": 360,
"step-price": 600,
"step_type": "single",
"comment": "single tariff-step"
},
{
"step-start": "now",
"step-duration": 420,
"step-price": 700,
"step_type": "single"
},
{
"step-start": "now",
"step-duration": 1440,
"step-price": 800,
"step_type": "single"
},
{
"step-start": "now",
"step-duration": 2880,
"step-price": 1600,
"step_type": "single"
},
{
"step-start": "now",
"step-duration": 4320,
"step-price": 2400,
"step_type": "single"
},
{
"step-start": "now",
"step-duration": 5400,
"step-price": 3200,
"step_type": "single"
},
{
"step-start": "now",
"step-duration": 7440,
"step-price": 4000,
"step_type": "single"
}
],
"comment": "not mentioning monday-sunday means that",
"comment": "for monday-sunday apply settings from top-half",
"comment": "of tariff-file"
}
}
\end{minted}
\subsection{Several service time ranges per day. Scaling factor}
\subsubsection{Stockerau}
\label{Stockerau}
\begin{enumerate}
\item[$\bullet$] Service time ranges:
\begin{enumerate}
\item Monday Friday: $08:0012:00$ and $13:30-18:00$
\item Saturday: $08:00-12:00$
\item Sunday and special days (holidays, open for sale days)
are free.
\end{enumerate}
\item[$\bullet$] Prices:
\begin{enumerate}
\item first 30 minutes: 70 cent
\item 60 minutes: 1,40 euros
\item 120 minutes: 2,80 euros
\item 180 minutes: 4,20 euros
\item 240 minutes: 5,60 euros
\end{enumerate}
\item[$\bullet$] Minimal parking time: 30 minutes.
\item[$\bullet$] Minimal parking price: 70 cent.
\item[$\bullet$] Maximal parking time: 257 minutes.
\item[$\bullet$] Maximal parking price: 6 euros.
\item[$\bullet$] Allow overpay: no.
\item[$\bullet$] Carry over: yes.
\item[$\bullet$] Prepaid: yes.
\item[$\bullet$] Smallest possible coin: 10 cent.
\end{enumerate}
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"project": "Stockerau",
"version": "1.0.0",
"product": "short-term-parking",
"payment-settings": [
{
"min-time": 30,
"max-time": 257,
"min-price": 70,
"max-price": 600,
"allow-overpay": true
}
],
"service-settings": [
{
"service-ranges": [
{
"service-start": "08:00",
"service-end": "12:00"
},
{
"service-start": "13:30",
"service-end": "18:00"
}
]
}
],
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "08:00"
},
{
"prepaid-start": "12:00",
"prepaid-end": "13:30"
},
{
"prepaid-start": "18:00",
"prepaid-end": "24:00"
},
}
],
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "00:00",
"carry-over-end": "08:00"
},
{
"carry-over-start": "12:00",
"carry-over-end": "13:30"
},
{
"carry-over-start": "18:00",
"carry-over-end": "24:00"
},
]
}
],
"tariff-steps": [
{
"step-start": "now",
"step-duration": 30,
"step-price": 70
},
{
"step-duration": 4,
"step-price": 10
"comment": 34
},
{
"step-duration": 5,
"step-price": 10
"comment": 39
},
{
"step-duration": 4,
"step-price": 10
"comment": 43
},
{
"step-duration": 4,
"step-price": 10
"comment": 47
},
{
"step-duration": 4,
"step-price": 10
"comment": 51
},
{
"step-duration": 5,
"step-price": 10
"comment": 56
},
{
"step-duration": 4,
"step-price": 10
"comment": 60
},
{
"step-duration": 4,
"step-price": 10
"comment": 64
},
{
"step-duration": 5,
"step-price": 10
"comment": 69
},
{
"step-duration": 4,
"step-price": 10
"comment": 73
},
{
"step-duration": 4,
"step-price": 10
"comment": 77
},
{
"step-duration": 4,
"step-price": 10
"comment": 81
},
{
"step-duration": 5,
"step-price": 10
"comment": 86
},
{
"step-duration": 4,
"step-price": 10
"comment": 90
},
{
"step-duration": 4,
"step-price": 10
"comment": 94
},
{
"step-duration": 5,
"step-price": 10
"comment": 99
},
{
"step-duration": 4,
"step-price": 10
"comment": 103
},
{
"step-duration": 4,
"step-price": 10
"comment": 107
},
{
"step-duration": 4,
"step-price": 10
"comment": 111
},
{
"step-duration": 5,
"step-price": 10
"comment": 116
},
{
"step-duration": 4,
"step-price": 10
"comment": 120
},
{
"step-duration": 4,
"step-price": 10
"comment": 124
},
{
"step-duration": 5,
"step-price": 10
"comment": 129
},
{
"step-duration": 4,
"step-price": 10
"comment": 133
},
{
"step-duration": 4,
"step-price": 10
"comment": 137
},
{
"step-duration": 4,
"step-price": 10
"comment": 141
},
{
"step-duration": 5,
"step-price": 10
"comment": 146
},
{
"step-duration": 4,
"step-price": 10
"comment": 150
},
{
"step-duration": 4,
"step-price": 10
"comment": 154
},
{
"step-duration": 5,
"step-price": 10
"comment": 159
},
{
"step-duration": 4,
"step-price": 10
"comment": 163
},
{
"step-duration": 4,
"step-price": 10
"comment": 167
},
{
"step-duration": 4,
"step-price": 10
"comment": 171
},
{
"step-duration": 5,
"step-price": 10
"comment": 176
},
{
"step-duration": 4,
"step-price": 10
"comment": 180
},
{
"step-duration": 4,
"step-price": 10
"comment": 184
},
{
"step-duration": 5,
"step-price": 10
"comment": 189
},
{
"step-duration": 4,
"step-price": 10
"comment": 193
},
{
"step-duration": 4,
"step-price": 10
"comment": 197
},
{
"step-duration": 4,
"step-price": 10
"comment": 201
},
{
"step-duration": 5,
"step-price": 10
"comment": 206
},
{
"step-duration": 4,
"step-price": 10
"comment": 210
},
{
"step-duration": 4,
"step-price": 10
"comment": 214
},
{
"step-duration": 5,
"step-price": 10
"comment": 219
},
{
"step-duration": 4,
"step-price": 10
"comment": 223
},
{
"step-duration": 4,
"step-price": 10
"comment": 227
},
{
"step-duration": 4,
"step-price": 10
"comment": 231
},
{
"step-duration": 5,
"step-price": 10
"comment": 236
},
{
"step-duration": 4,
"step-price": 10
"comment": 240
},
{
"step-duration": 4,
"step-price": 10
"comment": 244
},
{
"step-duration": 5,
"step-price": 10
"comment": 249
},
{
"step-duration": 4,
"step-price": 10
"comment": 253
},
{
"step-duration": 4,
"step-price": 10
"comment": 257
}
],
"comment": "monday-friday not really necessary",
"monday": [{
"default": {
"comment": "settings from top half apply"
}
}],
"tuesday": [{
"2024-12-24": {
"comment": "Christmas",
"comment": "Public Holidays are free",
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "24:00"
}
]
}
],
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "00:00",
"carry-over-end": "24:00"
}
]
}
]
},
"default": {
"comment": "settings from top half apply"
}
}],
"wednesday": [{
"2024-12-25": {
"comment": "1st day of Christmas",
"comment": "Public Holidays are free",
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "24:00"
}
]
}
],
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "00:00",
"carry-over-end": "24:00"
}
]
}
]
},
"default": {
"comment": "settings from top half apply"
}
}],
"thursday": [{
"2024-12-26": {
"comment": "2nd day of Christmas",
"comment": "Public Holidays are free",
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "24:00"
}
]
}
],
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "00:00",
"carry-over-end": "24:00"
}
]
}
]
},
"default": {
"comment": "settings from top half apply"
}
}],
"friday": [{
"default": {
"comment": "settings from top half apply"
}
}],
"saturday": [{
"default": {
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "08:00"
},
{
"prepaid-start": "12:00",
"prepaid-end": "24:00"
}
]
}
],
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "00:00",
"carry-over-end": "08:00"
},
{
"carry-over-start": "12:00",
"carry-over-end": "24:00"
}
]
}
],
"service-settings": [
{
"service-ranges": [
{
"service-start": "08:00",
"service-end": "12:00"
}
]
}
]
}
}],
"sunday": [{
"default": {
"comment": "Sunday is free",
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "24:00"
}
]
}
],
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "24:00"
}
]
}
]
}
}]
}
}
\end{minted}
\subsection{Several service time ranges per day. Free special days.}
\subsubsection{Korneuburg}
\begin{enumerate}
\item[$\bullet$] Service time ranges:
\begin{enumerate}
\item Monday Friday: $08:0012:00$ and $14:00-18:00$
\item Saturday: $08:00-12:00$
\item Sunday and special days (holidays, open for sale days)
are free.
\end{enumerate}
\item[$\bullet$] Prices:
\begin{enumerate}
\item first 30 minutes: 60 cent
\item each following 5 minutes: 10 cent
\end{enumerate}
\item[$\bullet$] Minimal parking time: 30 minutes.
\item[$\bullet$] Minimal parking price: 60 euros.
\item[$\bullet$] Maximal parking time: 180 minutes.
\item[$\bullet$] Maximal parking price: 3,60 euros.
\item[$\bullet$] Allow overpay: yes.
\item[$\bullet$] Carry over: yes.
\item[$\bullet$] Prepaid: no.
\end{enumerate}
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"project": "Korneuburg",
"version": "1.0.0",
"product": "short-term-parking",
"payment-settings": [
{
"min-time": 30,
"max-time": 180,
"min-price": 60,
"max-price": 360,
"allow-overpay": true
}
],
"service-settings": [
{
"service-ranges": [
{
"service-start": "08:00",
"service-end": "12:00"
},
{
"service-start": "14:00",
"service-end": "18:00"
}
]
}
],
"comment": "no prepaid-settings",
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "12:00",
"carry-over-end": "14:00"
}
]
}
],
"tariff-steps": [
{
"step-start": "now",
"step-duration": 30,
"step-price": 60
},
{
"step-duration": 5,
"step-repetition-count": 30,
"step-price": 10,
"comment": "in total 150 minutes and cost 3 euros"
}
],
"comment": "monday-friday not really necessary",
"monday": [{
"default": {
"comment": "settings from top half apply"
}
}],
"tuesday": [{
"2024-12-24": {
"comment": "Christmas",
"comment": "Public Holidays are free",
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "24:00"
}
]
}
],
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "00:00",
"carry-over-end": "24:00"
}
]
}
]
},
"default": {
"comment": "settings from top half apply"
}
}],
"wednesday": [{
"2024-12-25": {
"comment": "1st day of Christmas",
"comment": "Public Holidays are free",
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "24:00"
}
]
}
],
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "00:00",
"carry-over-end": "24:00"
}
]
}
]
},
"default": {
"comment": "settings from top half apply"
}
}],
"thursday": [{
"2024-12-26": {
"comment": "2nd day of Christmas",
"comment": "Public Holidays are free",
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "24:00"
}
]
}
],
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "00:00",
"carry-over-end": "24:00"
}
]
}
]
},
"default": {
"comment": "settings from top half apply"
}
}],
"friday": [{
"default": {
"comment": "settings from top half apply"
}
}],
"saturday": [{
"default": {
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "00:00",
"carry-over-end": "08:00"
},
{
"carry-over-start": "12:00",
"carry-over-end": "24:00"
}
]
}
],
"service-settings": [
{
"service-ranges": [
{
"service-start": "08:00",
"service-end": "12:00"
}
]
}
]
}
}],
"sunday": [{
"default": {
"comment": "Sunday is free",
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "00:00",
"carry-over-end": "24:00"
}
]
}
]
}
}]
}
}
\end{minted}
\subsection{Several service time ranges per day. Free special days. No prepaid.}
\subsubsection{Kirchdorf}
\begin{enumerate}
\item[$\bullet$] Service time ranges:
\begin{enumerate}
\item Monday Friday: 08:00 12:00 and 14:00 - 18:00
\item Saturday: 08:00 - 12:00
\item Sunday and special days (holidays, open for sale days)
are free.
\end{enumerate}
\item[$\bullet$] Prices:
\begin{enumerate}
\item first 30 minutes: 30 cent
\item each following 5 minutes: 10 cent
\end{enumerate}
\item[$\bullet$] Minimal parking time: 30 minutes.
\item[$\bullet$] Minimal parking price: 30 cent.
\item[$\bullet$] Maximal parking time: 90 minutes.
\item[$\bullet$] Maximal parking price: 1,50 euros.
\item[$\bullet$] Allow overpay: yes.
\item[$\bullet$] Carry over: yes.
\item[$\bullet$] Prepaid: yes.
\end{enumerate}
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"project": "Korneuburg",
"version": "1.0.0",
"product": "short-term-parking",
"payment-settings": [
{
"min-time": 30,
"max-time": 90,
"min-price": 30,
"max-price": 150,
"allow-overpay": true
}
],
"service-settings": [
{
"service-ranges": [
{
"service-start": "08:00",
"service-end": "12:00"
},
{
"service-start": "14:00",
"service-end": "18:00"
}
]
}
],
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "08:00"
},
{
"prepaid-start": "12:00",
"prepaid-end": "14:00"
},
{
"prepaid-start": "18:00",
"prepaid-end": "24:00"
}
]
}
],
"comment": "no carry-over-settings",
"tariff-steps": [
{
"step-start": "now",
"step-duration": 30,
"step-price": 60
},
{
"step-duration": 5,
"step-repetition-count": 30,
"step-price": 10,
"comment": "in total 150 minutes and cost 3 euros"
}
],
"comment": "monday-friday not really necessary",
"monday": [{
"default": {
"comment": "settings from top half apply"
}
}],
"tuesday": [{
"2024-12-24": {
"comment": "Christmas",
"comment": "Public Holidays are free",
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "24:00"
}
]
}
],
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "00:00",
"carry-over-end": "24:00"
}
]
}
]
},
"default": {
"comment": "settings from top half apply"
}
}],
"wednesday": [{
"2024-12-25": {
"comment": "1st day of Christmas",
"comment": "Public Holidays are free",
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "24:00"
}
]
}
],
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "00:00",
"carry-over-end": "24:00"
}
]
}
]
},
"default": {
"comment": "settings from top half apply"
}
}],
"thursday": [{
"2024-12-25": {
"comment": "2nd day of Christmas",
"comment": "Public Holidays are free",
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "24:00"
}
]
}
],
"carry-over-settings": [
{
"carry-over-ranges": [
{
"carry-over-start": "00:00",
"carry-over-end": "24:00"
}
]
}
]
},
"default": {
"comment": "settings from top half apply"
}
}],
"friday": [{
"default": {
"comment": "settings from top half apply"
}
}],
"saturday": [{
"default": {
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "08:00"
},
{
"prepaid-start": "12:00",
"prepaid-end": "24:00"
}
]
}
],
"service-settings": [
{
"service-ranges": [
{
"service-start": "08:00",
"service-end": "12:00"
}
]
}
]
}
}],
"sunday": [{
"default": {
"comment": "Sunday is free",
"prepaid-settings": [
{
"prepaid-ranges": [
{
"prepaid-start": "00:00",
"prepaid-end": "24:00"
}
]
}
],
}
}]
}
}
\end{minted}
\subsection{Different max-price for Sunday. 1 minute resolution for
last tariff-step}
\subsubsection{Bad Neuenahr}
See section \ref{top-and-bottom}.
%\subsection{Weiden}
%\subsection{Forchach}
%\subsection{Schnals}
\subsection{Set min-time and/or min-price at runtime}
\subsubsection{Valser Alm: Fane}
\begin{enumerate}
\item[$\bullet$] Service time ranges: Monday Sunday: 00:00 24:00.
\item[$\bullet$] Minimal parking time: until 14:00 if arrival time is
before 14:00. Otherwise until 24:00.
\item[$\bullet$] Minimal parking price: 8 euros if arrival time is
before 14:00. Otherwise 5 euros.
\item[$\bullet$] Maximal parking time: unlimited.
\item[$\bullet$] Maximal parking price: unlimited.
\item[$\bullet$] Allow overpay: no.
\item[$\bullet$] Prepaid: no.
\end{enumerate}
\begin{minted}[frame=single,
framesep=3mm,
linenos=true,
xleftmargin=21pt,
tabsize=4]{js}
{
"header" : {
"project": "Valser Alm (Fane)",
"version": "1.0.0",
"product": "short-term-parking",
"info": ""
},
"top" : {
"payment-settings": {
"min-time": {
"cond": [
{
"current-wallclock-parking-time": {
"<": "14:00",
"then": "14:00"
}
},
{
"else": "24:00"
}
]
},
"min-price": {
"cond": [
{
"current-wallclock-parking-time": {
"<": "14:00",
"then": 800
}
},
{
"else": 500
}
]
},
"max-time": "unlimited",
"max-price": "unlimited",
"allow-overpay": true,
"prepaid": false
},
"service-settings": [
{
"service-ranges": [
{
"service-start": "00:00",
"service-end": "24:00"
}
]
}
],
"comment": "no prepaid-settings",
"comment": "no carry-over-settings",
"tariff-steps": [
{
"step-start": "now",
"step-duration": "min-time"
"step-price": "min-price"
},
{
"step-duration": 1440,
"step-start": "00:00",
"step-end": "24:00",
"step-repetition-count": "unlimited",
"step-price": 800
}
]
},
"bottom" : {
"comment": "monday-sunday not necessary",
"comment": "take implicitly settings from top half"
}
}
}
\end{minted}
\subsubsection{Valser Alm: Specker}
Two different \gls{tariff-file}s for this site: \textbf{PKW} and \textbf{BUS}.
% TODO: eine aufspaltung zwichen arrival-time und start-time. insbesondere
% bei prepaid ist das wichti.
\begin{enumerate}
\item[$\bullet$] Service time ranges: Monday Sunday: 07:00 19:00.
\item[$\bullet$] Minimal parking time: 12 hours.
\item[$\bullet$] Maximal parking time: 7 days.
\item[$\bullet$] Allow overpay: no.
\item[$\bullet$] Prepaid: yes.
\item[$\bullet$] Carry over: yes.
\item[] \textbf{PKW}
\begin{enumerate}
\item[$\bullet$] Minimal parking price: 6 euros.
\item[$\bullet$] Maximal parking price: 42 euros.
\end{enumerate}
\item[] \textbf{BUS}
\begin{enumerate}
\item[$\bullet$] Minimal parking price: 30 euros.
\item[$\bullet$] Maximal parking price: 210 euros.
\end{enumerate}
\end{enumerate}
%\subsection{Sexten}
%\subsection{Wolkenstein}
\section{Known issues}
\pagebreak
% Print the glossary
\printglossaries
\end{document}