Post by Heiner RichterLiebe Fachleute,
hat es jemand schon mal mit der tikzlibrary calendar geschafft, die paar Tage des Vor- und folgenden Monats automatisch (zB in blasser Schrift, die kein Problem wäre) den einzelnen Monaten jeweils hinzuzufügen?
Ich frage mich, ob man unbedingt TikZ und die calendar-Library braucht,
um einen Kalender zu setzen.
Vielleicht braucht man weniger Masochismus, wenn man die von
pgfcalendar.sty zur Verfügung gestellte Schleife verwendet und
selbst etwas bastelt, was einem Tabellen-Umgebungen produziert.
Aber sei es drum.
Ich denke, ein Problem könnte darin bestehen, einen Algorithmus zu
formulieren, der es erlaubt, zwischen Tagen, die zum Monat gehören
und zwischen Tagen, die nicht zum Monat gehören, zu unterscheiden,
und, wenn beim Monatswechsel Wochentage wiederholt werden, die
jeweiligen Zähler richtig zurück zu setzen.
Ich habe jetzt spaßeshalber eine geschlagene Dreiviertelstunde damit
zugebracht, etwas zusammenzufrickeln, was man als Grundidee
auffassen könnte.
Ich habe es mir aber geschenkt, noch länger herumzufrickeln, um eine
wirklich perfekte Platzierung der Elemente auf dem Blatt zu erreichen -
mein Masochismus hat nicht ausgereicht, anhand von Quellcode
herauszufinden, was TikZ in Sachen Positionierung genau veranstaltet.
Zur Grundidee:
Wenn die zu einer bestimmten Zeitspanne gehörenden Tage in einer Schleife
in einen Monatskalender bzw. Wochentagskalender gesetzt werden sollen,
sodass zu jedem Monat eine Monatsüberschrift und eine Tabellenbeschriftung
mit Wochentagen gehört, muss man in der Schleife wohl zwischen sechs
Situationen unterscheiden.
Dazu braucht es eine Variable "Laufender Monat", die zwölf verschiedene
Werte annehmen kann und die Nummer desjenigen Monats angibt, für den
gerade der Kalender gebastelt wird.
Dazu braucht es außerdem eine Variable "Situation", die sechs verschiedene
Werte annehmen kann, von denen jeder für eine bestimmte Situation steht.
Am Anfang einer Iteration gibt diese Variable an, welche Situation in
der vorherigen Iteration bzw. zu Beginn der Schleife vorlag.
Anhand dieser Information und sonstigen Umständen kann gschlossen werden,
welche Situation in dieser Iteration vorliegt und der Wert der Variablen
"Situation" entsprechend geändert werden.
Dann kann, bevor die Tageszahl gesetzt wird, Code ausgeführt werden, je
nachdem, welche Situation in dieser Iteration gegeben ist.
Solcher Code kann z.B. Anweisungen zum Ändern der Textfarbe, etwa
durch Anhängen von key=value-Paaren an die entsprechenden Styles,
enthalten.
Die sechs Situationen sind:
- Situation "just initialized".
Diese Situation liegt nur vor, bevor die Schleife begonnen wird.
Sie liegt nie vor, wenn eine Tageszahl gesetzt wird.
- Situation "before the date range".
(Man bedenke, dass immer ganze Kalenderwochen ausgegeben werden.)
Diese Situation liegt vor, wenn ein Tag gesetzt wird, der in der
selben Woche wie das erste Datum des Datumsbereichs, aber früher als
das erste Datum des Datumsbereichs liegt.
- Situation "before the month".
Diese Situation liegt vor, wenn ein Tag gesetzt wird, der im
Datumsbereich früher als der erste des Monats, aber nicht früher als
das erste Datum des Datumsbereichs liegt.
- Situation "in the month".
Diese Situation liegt vor, wenn ein Tag gesetzt wird, der im
Datumsbereich und im betreffenden Monat liegt.
- Situation "after the month".
Diese Situation liegt vor, wenn ein Tag gesetzt wird, der im
Datumsbereich später als der letzte des Monats, aber nicht später als
das letzte Datum des Datumsbereichs liegt.
- Situation "after the date range".
(Man bedenke, dass immer ganze Kalenderwochen ausgegeben werden.)
Diese Situation liegt vor, wenn ein Tag gesetzt wird, der in der
selben Woche wie das letzte Datum des Datumsbereichs, aber später als
das letzte Datum des Datumsbereichs liegt.
Je nachdem, welche Situation in der vorigen Iteration gegeben war, muss
man in der laufenden Iteration prüfen, um festzustellen, welche
Situation diesmal gegeben ist, und den Wert der Variablen "Situation"
entsprechend ändern:
- Wenn in der vorherigen Iteration die Situation
"just initialized"
gegeben war:
----------------------------------------------
* "Monatsüberschriftsroutine" ausführen.
- Wenn in der vorherigen Iteration die Situation
"before the date range"
gegeben war:
----------------------------------------------
* Wenn das Datum nicht früher als das Startdatum liegt, dann
- wenn der Monat des Datums ungleich dem "Laufenden Monat" ist,
setze Situation := "before the month".
- wenn der Monat des Datums gleich dem "Laufenden Monat" ist,
setze Situation := "in the month".
- Wenn in der vorherigen Iteration die Situation
"before the month"
gegeben war:
----------------------------------------------
- Wenn das Datum der Erste des (Folge)Monats ist, dann setze
Situation := "in the month".
- Wenn in der vorherigen Iteration die Situation
"in the month"
gegeben war:
----------------------------------------------
* Wenn das Datum später ist als das Enddatum, setze
Situation:="after the date range".
* Wenn das Datum nicht später ist als das Enddatum und das Datum
der Monatserste ist und
- es Montag ist, führe die "Monatsüberschriftsroutine" aus.
- es nicht Montag ist, setze Situation:="after the month".
- Wenn in der vorherigen Iteration die Situation
"after the month"
gegeben war:
----------------------------------------------
* Wenn das Datum später ist als das Enddatum, setze
Situation:="after the date range".
* Wenn das Datum nicht später ist als das Enddatum und wenn
- es Montag ist, führe die "Monatsüberschriftsroutine" aus.
- Wenn in der vorherigen Iteration die Situation
"after the date range"
gegeben war:
----------------------------------------------
[Situation nicht verändern]
Während die Situation in der laufenden Iteration bestimmt wird, kann es
dazu kommen, dass eine "Monatsüberschriftsroutine" ausgeführt wird,
die die Monatsüberschrift und die Wochentagstabellenbeschriftung setzt
und ggfs zwecks Wiederholung der Tage, die zur ersten Woche des
Monates gehören, aber nicht im Monat liegen, den Datumszähler auf den
nicht später gelegenen Montag zurücksetzt, insgesamt also folgendes tut:
1. Monatsüberschrift und Wochentagstabellenbeschriftung setzen.
2. Die Nummer des Monats, für den jetzt der Monatskalender gesetzt werden soll,
in der Variablen "Laufender Monat" abspeichern.
3. "Situation anpassen":
Wenn nicht "just initialized": Datum auf den Monatsersten zurücksetzen.
Datum auf Montag zurücksetzen.
Wenn das Datum vor dem Startdatum liegt, setze Situation:="before the date range".
Wenn das Datum nicht vor dem Startdatum und im laufenden Monat liegt,
setze Situation:="in the month".
Wenn das Datum nicht vor dem Startdatum und nicht im laufenden Monat liegt,
setze Situation:="before the month".
Man muss also, bevor die Schleife gestartet wird,
- Situation = "just initialized" setzen,
- Start- und Enddatum als julianische Datumsnummern speichern und
- danach das Enddatum auf den nächsten Sonntag legen, der nicht früher
als das Enddatum liegt.
In der Schleife, immer bevor ein Kalendertag geschrieben wird, also über
execute before day scope={...}, musss abgefragt werden, welche der sechs
Situationen beim Ausgeben der Tagesnummer in der vorigen Iteration
gegeben war und die entsprechende Aktion ausgeführt werden, um ggfs. die
Situation anzupassen.
Nach dem Anpassen der Situation ist eine der Situationen
"before the date range", "before the month", "in the month",
"after the month", "after the date range" gegeben.
Danach kann in dem local scope, den TeX eröffnet, um den Kalendertag
zu schreiben, also über execute at begin day scope={...} , bevor die
Tagesnummer gesetzt wird, Code ausgeführt werden, je nachdem, welche
Situation in dieser Iteration gegeben ist.
Solcher Code kann z.B. Anweisungen zum Ändern der Textfarbe, etwa
durch Anhängen von key=value-Paaren an die entsprechenden Styles,
enthalten.
Sowohl beim Anpassen der Situation als auch beim Setzen der Tageszahl
muss verzweigt werden, je nachdem, welche der sechs Situationen
vorliegt.
Im untenstehenden Beispiel
- haben alle Makros, die ich selbst geschrieben habe, das Namenspräfix
"MYSTUFF".
- dient das Makro \MYSTUFFCurrentMonth als Variable "Laufender Monat",
für den gerade der Kalender gebastelt wird.
- dient das Makro \MYSTUFFSaveCurrentMonth dazu, die Variable
"Laufender Monat" anhand des Datums, für das in der laufenden
Iteration der Kalendertag geschrieben werden soll, zu aktualisieren.
- dient das Makro \MYSTUFFSituation als Variable "Situation".
- dient das Makro \MYSTUFFSetSituation{<Situation>};
Situation = just initialized | before the date range | before the month |
in the month | after the month | after the date range
dazu, den Wert der Variablen "Situation" global zu ändern.
- dient das Makro
\Situationfork{<tokens wenn Situation = just initialized>}%
{<tokens wenn Situation = before the date range>}%
{<tokens wenn Situation = before the month>}%
{<tokens wenn Situation = in the month>}%
{<tokens wenn Situation = after the month>}%
{<tokens wenn Situation = after the date range>}%
dazu, zu verzweigen, je nachdem, welche Situation gegeben ist.
- hat das Makro \Kalenderblatt ein optionales Argument, in dem man
für jede der Situationen "before the date range", "before the month",
"in the month", "after the month", "after the date range"
mittels key=value-Interface angeben kann, welcher Code direkt vor
dem Setzen der Tagesnummer ausgeführt werden soll, wenn diese
Situation gegeben ist. Hier kann man z.B. Direktiven zur Farbänderung
angeben. Die Keys heißen natürlich "before the date range",
"before the month", "in the month", "after the month",
"after the date range" und gehören zum pgfkeys-Pfad
/MYSTUFF/Kalenderblatt/.
- wird die "Monatsüberschriftsroutine" durch das Makro
"\MYStuffKalenderblattUeberschrift" initiiert.
- Ist die julianische Datumsnummer des Startdatums in \MYSTUFFStartdate
gespeichert.
- Ist die julianische Datumsnummer des Endatums in \MYSTUFFEnddate
gespeichert.
Mit freundlichem Gruß
Ulrich
%\errorcontextlines=10000
\documentclass{scrartcl}
\usepackage[ngerman]{babel}
\usepackage[ngerman]{translator}
\usepackage{tikz}
\usetikzlibrary{calendar}
%\usetikzlibrary{babel}
\makeatletter
% ======================================================
% Infrastruktur fürs Verwalten der Variable "Situation":
% ======================================================
\newcommand\MYSTUFFSituation{just initialized}%
\newcommand\MYSTUFFSetSituation[1]{%
\xdef\MYSTUFFSituation{\unexpanded{#1}}%
}%
\newcommand\MYSTUFFSituationfork{%
\expandafter\***@Situationfork\expandafter{\MYSTUFFSituation}%
}%
\newcommand\***@Situationfork[7]{%
\MYSTUFF@@Situationfork
!#1!before the date range!before the month!in the month!after the month!after the date range!{#2}%
!just initialized!#1!before the month!in the month!after the month!after the date range!{#3}%
!just initialized!before the date range!#1!in the month!after the month!after the date range!{#4}%
!just initialized!before the date range!before the month!#1!after the month!after the date range!{#5}%
!just initialized!before the date range!before the month!in the month!#1!after the date range!{#6}%
!just initialized!before the date range!before the month!in the month!after the month!#1!{#7}!!!!%
}%
\@ifdefinable\MYSTUFF@@Situationfork{%
\long\def\MYSTUFF@@Situationfork
#1!just initialized!before the date range!before the month!in the month!after the month!after the date range!#2#3!!!!{#2}%
}%
\newcommand*\MYSTUFFSpace{ }%
\newcommand\MYSTUFFCurrentMonth{}%
\newcommand\MYSTUFFSaveCurrentMonth{%
\xdef\MYSTUFFCurrentMonth{\the\numexpr(\pgfcalendarcurrentmonth)\relax}%
}%
% =============================================================
% Key=Value-Interface, um für jede der Situationen
% "before the date range", "before the month", "in the month",
% "after the month", "after the date range"
% anzugeben, welcher Code direkt vor dem Setzen der Tagesnummer
% ausgeführt werden soll, wenn diese Situation gegeben ist:
% =============================================================
\pgfkeys{%
/MYSTUFF/Kalenderblatt/.cd,
before the date range/.initial = {},
before the date range/.default = {},
before the month/.initial = {},
before the month/.default = {},
in the month/.initial = {},
in the month/.default = {},
after the month/.initial = {},
after the month/.default = {},
after the date range/.initial = {},
after the date range/.default = {},
day heading/.initial = {},
day heading/.default = {},
month heading/.initial = {},
month heading/.default = {},
}%
% =============================================================
% \Kalenderblatt[
% before the date range=...,
% before the month=...,
% in the month=...,
% after the month=...,
% after the date range=...,
% ]{YYYY-MM-DD to YYYY-MM-DD}
% =============================================================
\newcommand\Kalenderblatt[2][]{%
\begingroup
\pgfkeys{%
% /tikz/inner sep = 0pt,
/tikz/day xshift=\the\dimexpr.166666667\textwidth \relax,
/tikz/day yshift=\the\dimexpr\textheight / 21 \relax,
/MYSTUFF/Kalenderblatt/.cd, #1%
}%
\MYSTUFFSetSituation{just initialized}%
\begingroup
% Speichere Start- und Stopdatum im ISO-Format in Makros \***@lib@***@start / \***@lib@***@end:
\***@lib@***@parse#2\relax
% Konvertiere Start in julianische Datumsnummer und speichere als \MYSTUFFStartdate:
\pgfcalendardatetojulian{\***@lib@***@start}{\pgfcalendarcurrentjulian}%
\xdef\MYSTUFFStartdate{\the\pgfcalendarcurrentjulian}%
% Konvertiere Stopdatum in julianische Datumsnummer und speichere als \MYSTUFFEnddate::
\pgfcalendardatetojulian{\***@lib@***@end}{\pgfcalendarcurrentjulian}%
\xdef\MYSTUFFEnddate{\the\pgfcalendarcurrentjulian}%
% Berechne den Wochentag des Stopdatums in den Zähler \***@tempcntb :
\pgfcalendarjuliantoweekday{\pgfcalendarcurrentjulian}{\***@tempcntb}%
% Zähle das Stopdatum bis zum nächsten Sonntag hoch:
\pgfcalendarcurrentjulian=\the\numexpr(\pgfcalendarcurrentjulian+6-\***@tempcntb)\relax
% Konvertiere hochgezähltes Stopdatum in Iso-Datumskomponenten:
\pgfcalendarjuliantodate{\pgfcalendarcurrentjulian}{\myyear}{\mymonth}{\myday}%
\expanded{\unexpanded{\endgroup
\begin{tikzpicture}[thick]%
\calendar[%
dates=}\***@lib@***@start\space to\space\myyear-\mymonth-\myday},
week list,
month yshift=0cm,
month xshift=0cm,
month text=\%mt \%y0,
every month/.append style={anchor=base},
every day/.append style={anchor=base},
execute before day scope={%
% Situation anpassen:
\MYSTUFFSituationfork{%
% <tokens wenn Situation = just initialized>%
% * führe die "Monatsüberschriftsroutine" aus.
\MYStuffKalenderblattUeberschrift
}{%
% <tokens wenn Situation = before the date range>%
% * Wenn das Datum nicht früher als das Startdatum liegt, dann
% - wenn der Monat des Datums ungleich dem "Laufenden Monat" ist,
% setze Situation := "before the month".
% - wenn der Monat des Datums gleich dem "Laufenden Monat" ist,
% setze Situation := "in the month".
\ifnum\pgfcalendarcurrentjulian<\MYSTUFFStartdate\MYSTUFFSpace\else
\ifnum\pgfcalendarcurrentmonth=\MYSTUFFCurrentMonth\MYSTUFFSpace
\MYSTUFFSetSituation{in the month}%
\else
\MYSTUFFSetSituation{before the month}%
\fi
\fi
}{%
% <tokens wenn Situation = before the month>%
% * Wenn das Datum der Erste des (Folge)Monats ist, dann setze
% Situation := "in the month".
\ifdate{day of month=1}{\MYSTUFFSetSituation{in the month}}{}%
}{%
% <tokens wenn Situation = in the month>%
% * Wenn das Datum später ist als das Enddatum, setze
% Situation:="after the date range".
% * Wenn das Datum nicht später ist als das Enddatum und das Datum
% der Monatserste ist und
% - es Montag ist, führe die "Monatsüberschriftsroutine" aus.
% - es nicht Montag ist, setze Situation:="after the month".
\ifnum\pgfcalendarcurrentjulian>\MYSTUFFEnddate\MYSTUFFSpace
\MYSTUFFSetSituation{after the date range}%
\else
\ifdate{day of month=1}{%
\ifdate{Monday}{\MYStuffKalenderblattUeberschrift}{\MYSTUFFSetSituation{after the month}}%
}{}%
\fi
}{%
% <tokens wenn Situation = after the month>%
% * Wenn das Datum später ist als das Enddatum, setze
% Situation:="after the date range".
% * Wenn das Datum nicht später ist als das Enddatum und wenn
% - es Montag ist, führe die "Monatsüberschriftsroutine" aus.
\ifnum\pgfcalendarcurrentjulian>\MYSTUFFEnddate\MYSTUFFSpace
\MYSTUFFSetSituation{after the date range}%
\else
\ifdate{Monday}{\MYStuffKalenderblattUeberschrift}{}%
\fi
}{%
% <tokens wenn Situation = after the date range>%
}%
},
execute at begin day scope={%
% Anweisungen gemäß Situation:
\MYSTUFFSituationfork
{}% <- Die Situation "just initialized" sollte jetzt nicht mehr gegeben sein.
{\pgfkeysvalueof{/MYSTUFF/Kalenderblatt/before the date range}}%
{\pgfkeysvalueof{/MYSTUFF/Kalenderblatt/before the month}}%
{\pgfkeysvalueof{/MYSTUFF/Kalenderblatt/in the month}}%
{\pgfkeysvalueof{/MYSTUFF/Kalenderblatt/after the month}}%
{\pgfkeysvalueof{/MYSTUFF/Kalenderblatt/after the date range}}%
},
];
\end{tikzpicture}
\endgroup
}%
\newcommand\MYStuffKalenderblattUeberschrift{%
% ------------------------------------------------------------
% Monatsüberschrift und Wochentagstabellenbeschriftung setzen:
% ------------------------------------------------------------
{%
% Mittels \pgftransformxshift die x-Koordinate horizontal in die
% horizontale Bildmitte verschieben:
% Der Kalender hat eine Geaamtbreite von sechs Kalenderspaltenabständen.
% Der Kalenderspaltenabstand ist (\***@lib@***@xshift).
% Der Kalender hat also eine Gesamtbreite von 6 * (\***@lib@***@xshift),
% bzw. der Kalender hat eine Gesamtbreite von
% ((\***@lib@***@width)-1)*(\***@lib@***@xshift).
% Davon die Hälfte:
\pgftransformxshift{(((\***@lib@***@width)-1)*(\***@lib@***@xshift))/2}%
\pgftransformyshift{(\***@lib@***@yshift)/3}%
\pgfkeysvalueof{/MYSTUFF/Kalenderblatt/month heading}%
\tikzmonthcode
}%
% ------------------------------------------------
% Wochentagstabellenbeschriftung setzen:
% ------------------------------------------------
\pgftransformyshift{-(\***@lib@***@yshift)}%
\foreach \d/\l in {0/Mo,1/Di,2/Mi,3/Do,4/Fr,5/Sa,6/So} {
\pgftransformxshift{(\d)*(\***@lib@***@xshift)}%
\pgftransformyshift{(\***@lib@***@yshift)}%
\pgfkeysvalueof{/MYSTUFF/Kalenderblatt/day heading}%
\node[every day, anchor=base]{\l};%
}%
% ------------------------------------------------
% Laufenden Monat abspeichern:
% ------------------------------------------------
\MYSTUFFSaveCurrentMonth
% ------------------------------------------------
% Gggfs Datum zurücksetzen und Situation anpassen:
% ------------------------------------------------
\MYSTUFFSituationfork{\@firstoftwo}{\@secondoftwo}{\@secondoftwo}{\@secondoftwo}{\@secondoftwo}{\@secondoftwo}%
{}{%
\pgfcalendarcurrentjulian=\the\numexpr\pgfcalendarcurrentjulian-\pgfcalendarcurrentday+1\relax
\pgfcalendarjuliantodate{\pgfcalendarcurrentjulian}{\pgfcalendarcurrentyear}{\pgfcalendarcurrentmonth}{\pgfcalendarcurrentday}%
\pgfcalendarjuliantoweekday{\pgfcalendarcurrentjulian}{\***@tempcntb}%
\edef\pgfcalendarcurrentweekday{\the\***@tempcntb}%
}%
\pgfcalendarcurrentjulian=\the\numexpr\pgfcalendarcurrentjulian-\pgfcalendarcurrentweekday\relax
\pgfcalendarjuliantodate{\pgfcalendarcurrentjulian}{\pgfcalendarcurrentyear}{\pgfcalendarcurrentmonth}{\pgfcalendarcurrentday}%
\pgfcalendarjuliantoweekday{\pgfcalendarcurrentjulian}{\***@tempcntb}%
\edef\pgfcalendarcurrentweekday{\the\***@tempcntb}%
\ifnum\pgfcalendarcurrentjulian<\MYSTUFFStartdate\MYSTUFFSpace
\MYSTUFFSetSituation{before the date range}%
\else
\ifnum\pgfcalendarcurrentmonth=\MYSTUFFCurrentMonth\MYSTUFFSpace
\MYSTUFFSetSituation{in the month}%
\else
\MYSTUFFSetSituation{before the month}%
\fi
\fi
}%
\makeatother
\pagestyle{empty}
\begin{document}
\enlargethispage{2cm}
\hrule height 0pt \kern -2cm
\section{Datumsbereich: 2023-10-31 to 2023-12-26}
\begin{itemize}
\item Jedes Datum des Datumsbereichs muss in genau einem Monatskalender normal
in schwarz erscheinen.
\item Der 30. Oktober 2023 liegt in der ersten Woche des Datumsbereiches, gehört
aber nicht zum Datumsbereich und ist deshalb sowohl im Monatskalender für
Oktober als auch im Monatsalender für November grau hinterlegt.
\item Der 1. und 2. und 3. und 4. und 5. November liegen in der letzten
Oktoberwoche, aber nicht im Oktober und sind deshalb im Monatskalender
für Oktober grau.
\item Der 31. Oktober liegt in der ersten Novemberwoche, aber nicht
im November und ist deshalb im Monatskalender für November grau.
\item Der 1. und 2. und 3. Dezember liegen in der letzten Novemberwoche, aber
nicht im November und sind deshalb im Monatskalender für November grau.
\item Der 27. und 28. und 29. und 30. November liegen in der ersten
Dezemberwoche, aber nicht im Dezember und sind deshalb im Monatskalender
für Dezember grau.
\item Der 27. und 28. und 29. und 30. und 31. Dezember liegen in der letzten
Woche des Datumsbereicht, aber nicht im Datumsbereich und sind deshalb
grau hinterlegt.
\end{itemize}
\vfill
\noindent
\Kalenderblatt[%
% In den Werten der Keys "before the date range=..." etc. kann man mit \ifdate weiter
% verzweigen und z.B. bestimmte Tage der Woche anders einfärben.
before the date range=\pgfkeys{/tikz/every day/.append style={preaction={fill=black!20}, rectangle, draw, white}},
before the month=\pgfkeys{/tikz/every day/.append style={black!20}},
in the month=\pgfkeys{/tikz/every day/.append style={black}},
after the month=\pgfkeys{/tikz/every day/.append style={black!20}},
after the date range=\pgfkeys{/tikz/every day/.append style={preaction={fill=black!20}, rectangle, draw, white}},
day heading=\pgfkeys{/tikz/every day/.append style={font=\footnotesize\scshape}},
month heading=\pgfkeys{/tikz/every month/.append style={font=\Large\scshape}},
]{2023-10-31 to 2023-12-26}
\section{Datumsbereich: 2023-12-01 to 2023-12-last}
\noindent
\Kalenderblatt{2023-12-01 to 2023-12-last}
\end{document}