commit 3060d61279e908774d6d421e0de4a2aacfe03c47
Author: Peter Adam
Date: Tue Feb 3 13:46:49 2026 +0100
Initial commit: Brevet card LaTeX sources
Add LaTeX templates for 200km brevet cards with front and back
sides. Includes Docker-based build system and documentation.
Co-Authored-By: Claude Sonnet 4.5
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..96bfe5b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,24 @@
+# LaTeX build artifacts
+*.aux
+*.log
+*.out
+*.toc
+*.synctex.gz
+*.fls
+*.fdb_latexmk
+
+# Rendered PDFs
+*.pdf
+
+# macOS
+.DS_Store
+
+# Editor files
+*.swp
+*.swo
+*~
+.vscode/
+.idea/
+
+# Claude Code
+.claude/
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..f92184c
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,16 @@
+FROM texlive/texlive:latest
+
+# Install additional packages if needed
+RUN apt-get update && apt-get install -y \
+ make \
+ && rm -rf /var/lib/apt/lists/*
+
+# Set working directory
+WORKDIR /workspace
+
+# Copy project files
+COPY brevetkarte.tex .
+COPY cyclist-logo.png .
+
+# Default command
+CMD ["pdflatex", "-interaction=nonstopmode", "brevetkarte.tex"]
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..8220941
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,85 @@
+# Makefile for building Brevet card PDF in Docker
+
+IMAGE_NAME := brevetcard-builder
+CONTAINER_NAME := brevetcard-build
+TEX_FILE_FRONT := brevetkarte.tex
+TEX_FILE_BACK := brevetkarte-rueckseite.tex
+PDF_FILE_FRONT := brevetkarte.pdf
+PDF_FILE_BACK := brevetkarte-rueckseite.pdf
+
+.PHONY: all build clean build-image build-pdf build-front build-back run shell help
+
+# Default target
+all: build
+
+# Build both PDFs (builds image if needed, then compiles)
+build: build-image build-front build-back
+
+# Build Docker image
+build-image:
+ @echo "Building Docker image..."
+ docker build -t $(IMAGE_NAME) .
+
+# Compile both PDFs in Docker container
+build-pdf: build-front build-back
+
+# Compile front side PDF
+build-front:
+ @echo "Compiling front side LaTeX to PDF..."
+ docker run --rm \
+ -v $(PWD):/workspace \
+ $(IMAGE_NAME) \
+ pdflatex -interaction=nonstopmode $(TEX_FILE_FRONT)
+ @echo "PDF generated: $(PDF_FILE_FRONT)"
+
+# Compile back side PDF
+build-back:
+ @echo "Compiling back side LaTeX to PDF..."
+ docker run --rm \
+ -v $(PWD):/workspace \
+ $(IMAGE_NAME) \
+ pdflatex -interaction=nonstopmode $(TEX_FILE_BACK)
+ @echo "PDF generated: $(PDF_FILE_BACK)"
+
+# Run container interactively
+run:
+ docker run --rm -it \
+ -v $(PWD):/workspace \
+ $(IMAGE_NAME) \
+ /bin/bash
+
+# Open shell in container for debugging
+shell:
+ docker run --rm -it \
+ -v $(PWD):/workspace \
+ --entrypoint /bin/bash \
+ $(IMAGE_NAME)
+
+# Clean generated files
+clean:
+ @echo "Cleaning generated files..."
+ rm -f *.aux *.log *.out *.toc *.pdf
+
+# Clean everything including Docker image
+clean-all: clean
+ @echo "Removing Docker image..."
+ docker rmi $(IMAGE_NAME) 2>/dev/null || true
+
+# Rebuild from scratch
+rebuild: clean-all build
+
+# Show help
+help:
+ @echo "Brevet Card PDF Builder"
+ @echo ""
+ @echo "Available targets:"
+ @echo " make build - Build Docker image and compile both PDFs (default)"
+ @echo " make build-image - Build Docker image only"
+ @echo " make build-pdf - Compile both front and back PDFs"
+ @echo " make build-front - Compile front side PDF only"
+ @echo " make build-back - Compile back side PDF only"
+ @echo " make shell - Open interactive shell in container"
+ @echo " make clean - Remove generated files (aux, log, pdf)"
+ @echo " make clean-all - Remove all files and Docker image"
+ @echo " make rebuild - Clean everything and rebuild"
+ @echo " make help - Show this help message"
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..494fde3
--- /dev/null
+++ b/README.md
@@ -0,0 +1,124 @@
+# Brevet Card PDF Generator
+
+LaTeX-based generator for Audax Randonneurs Deutschland brevet cards with front and back sides for duplex printing.
+
+## Quick Start
+
+```bash
+# Build everything and generate both PDFs
+make build
+
+# The PDFs will be created as:
+# - brevetkarte.pdf (front side with participant info)
+# - brevetkarte-rueckseite.pdf (back side with control points)
+```
+
+## Prerequisites
+
+- Docker
+- Make
+
+## Usage
+
+### Build Both PDFs
+```bash
+make build
+```
+
+This will:
+1. Build the Docker image with TeXLive
+2. Compile `brevetkarte.tex` to `brevetkarte.pdf` (front side)
+3. Compile `brevetkarte-rueckseite.tex` to `brevetkarte-rueckseite.pdf` (back side)
+
+### Build Individual Sides
+
+```bash
+# Just build front side
+make build-front
+
+# Just build back side
+make build-back
+
+# Build both sides (without rebuilding Docker image)
+make build-pdf
+```
+
+### Other Commands
+
+```bash
+# Just build the Docker image
+make build-image
+
+# Open interactive shell in container
+make shell
+
+# Clean generated files (.aux, .log, .pdf)
+make clean
+
+# Clean everything including Docker image
+make clean-all
+
+# Rebuild from scratch
+make rebuild
+
+# Show help
+make help
+```
+
+## Files
+
+- `brevetkarte.tex` - LaTeX source for the front side (participant info)
+- `brevetkarte-rueckseite.tex` - LaTeX source for the back side (control points)
+- `cyclist-logo.png` - Audax Randonneurs logo (extracted from original)
+- `Dockerfile` - Docker image definition with TeXLive
+- `Makefile` - Build automation
+- `Brevet200km_2025_09_20_Namensseite_blanko.pdf` - Original front side template
+- `Brevet200km_2025_09_20_Kontrollseite.pdf` - Original back side template
+
+## Output
+
+### Front Side (brevetkarte.pdf)
+Contains two identical brevet cards that can be cut in half. Each card includes:
+- Participant information fields (Name, Address, etc.)
+- Event details (200km "Auf eine Pommes nach Belgien")
+- Randonneur Mondiaux rules
+- Homologation section
+- Start time: 8:30
+
+### Back Side (brevetkarte-rueckseite.pdf)
+Contains control points table (4 columns × 6 rows):
+- **Rows 1-3**: Control points for upper card
+ - Nr. 1: Start (Km 0 - Unisport, Bonn)
+ - Nr. 2: Km 57 - Nationalpark-Tor, Heimbach
+ - Nr. 3: Km 100 - Friterie "Au Petit Creux", Waimes
+ - Nr. 4: Km 165 - Mahlberg
+ - Nr. 5: Km 205 - Finish (Unisport, Bonn)
+- **Rows 4-6**: Control points for lower card (same as above, but Nr. 5: Km 214)
+- Empty columns for stamps/signatures
+- Control question for verification
+
+## Duplex Printing
+
+The PDFs are designed for duplex (double-sided) printing:
+1. Print `brevetkarte.pdf` on one side
+2. Print `brevetkarte-rueckseite.pdf` on the reverse side
+3. The columns and rows are aligned so that:
+ - Front side columns match back side columns
+ - Upper card (rows 1-3) aligns with front side upper card
+ - Lower card (rows 4-6) aligns with front side lower card
+4. Cut the sheet in half horizontally to create two separate brevet cards
+
+## Customization
+
+Edit `brevetkarte.tex` to modify front side:
+- Event name, date, and location
+- Distance (200km)
+- Start time
+- Club information
+- Brevet number format
+
+Edit `brevetkarte-rueckseite.tex` to modify back side:
+- Control point locations
+- Control times (von/bis)
+- Distances
+- Control questions
diff --git a/brevetkarte-rueckseite.tex b/brevetkarte-rueckseite.tex
new file mode 100644
index 0000000..48fd574
--- /dev/null
+++ b/brevetkarte-rueckseite.tex
@@ -0,0 +1,218 @@
+\documentclass[a4paper,10pt,landscape]{article}
+\usepackage[utf8]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage[landscape,top=0.8cm,bottom=0.8cm,left=0.8cm,right=0.8cm]{geometry}
+\usepackage{array}
+\usepackage{helvet}
+
+% Set sans-serif font as default
+\renewcommand{\familydefault}{\sfdefault}
+
+\setlength{\parindent}{0pt}
+\setlength{\tabcolsep}{3pt}
+\pagestyle{empty}
+
+% A4 landscape height: 21cm
+% Half height: 10.5cm from top of page
+% Top margin: 0.8cm
+% Row 4 should start at: 10.5 - 0.8 = 9.7cm from start of content
+%
+% Front side: each card is 8.5cm tall
+% So rows 1-3 should be: 8.5cm total (2.833cm each)
+% Gap after row 3: 9.7 - 8.5 = 1.2cm
+
+\newcommand{\rowheight}{2.833cm}
+
+\begin{document}
+
+% Upper card table (rows 1-3)
+\noindent
+\begin{tabular}{|p{6.6cm}|p{6.6cm}|p{6.6cm}|p{6.6cm}|}
+\hline
+% Row 1 (Upper card) - height 2.833cm
+\parbox[c][\rowheight][t]{6.5cm}{%
+\vspace{2mm}
+\textbf{Nr. 1:} Km 0 - Unisport\\
+Nachtigallenweg 86, Bonn\\
+\\
+\textbf{Kontrollzeit}\\
+von: 7:30\\
+bis: 8:30
+}
+&
+\parbox[c][\rowheight][c]{6.5cm}{%
+% Empty for stamps
+}
+&
+\parbox[c][\rowheight][t]{6.5cm}{%
+\vspace{2mm}
+\textbf{Nr. 4:} Km 165 Mahlberg Ecke K50,\\
+Breitestraße\\
+\textbf{Kontrollzeit}\\
+von: 13:21\\
+bis: 19:30
+}
+&
+\parbox[c][\rowheight][t]{6.5cm}{%
+\vspace{2mm}
+\textbf{Kontrollfrage:}\\
+Wann wurde das Kriegerdenkmal\\
+eingerichtet?
+}
+\\
+\hline
+
+% Row 2 (Upper card) - height 2.833cm
+\parbox[c][\rowheight][t]{6.5cm}{%
+\vspace{2mm}
+\textbf{Nr. 2:} Km 57 -- „Nationalpark-Tor" im\\
+alten Bahnhofsgebäude, Heimbach\\
+\\
+\textbf{Kontrollzeit}\\
+von: 9:11\\
+bis: 12:21
+}
+&
+\parbox[c][\rowheight][c]{6.5cm}{%
+% Empty for stamps
+}
+&
+\parbox[c][\rowheight][t]{6.5cm}{%
+\vspace{2mm}
+\textbf{Nr. 5:} Km 205 - Unisport\\
+Nachtigallenweg 86, Bonn\\
+\\
+\textbf{Kontrollzeit}\\
+von: 13:23\\
+bis: 21:00
+}
+&
+\parbox[c][\rowheight][c]{6.5cm}{%
+% Empty
+}
+\\
+\hline
+
+% Row 3 (Upper card) - height 2.833cm
+\parbox[c][\rowheight][t]{6.5cm}{%
+\vspace{2mm}
+\textbf{Nr. 3:} Km 100 - Friterie „Au Petit\\
+Creux" oder Total-Tankstelle, Ecke Rue\\
+de Botrange/Rue de Charmilles, Waimes\\
+\textbf{Kontrollzeit}\\
+von: 11:26\\
+bis: 15:10
+}
+&
+\parbox[c][\rowheight][c]{6.5cm}{%
+% Empty for stamps
+}
+&
+\parbox[c][\rowheight][c]{6.5cm}{%
+% Empty
+}
+&
+\parbox[c][\rowheight][c]{6.5cm}{%
+% Empty
+}
+\\
+\hline
+\end{tabular}
+
+\vspace{1.8cm}
+
+% Lower card table (rows 4-6)
+\noindent
+\begin{tabular}{|p{6.6cm}|p{6.6cm}|p{6.6cm}|p{6.6cm}|}
+\hline
+% Row 1 (Lower card)
+\parbox[c][\rowheight][t]{6.5cm}{%
+\vspace{2mm}
+\textbf{Nr. 1:} Km 0 - Unisport\\
+Nachtigallenweg 86, Bonn\\
+\\
+\textbf{Kontrollzeit}\\
+von: 7:30\\
+bis: 8:30
+}
+&
+\parbox[c][\rowheight][c]{6.5cm}{%
+% Empty for stamps
+}
+&
+\parbox[c][\rowheight][t]{6.5cm}{%
+\vspace{2mm}
+\textbf{Nr. 4:} Km 165 Mahlberg Ecke K50,\\
+Breitestraße\\
+\textbf{Kontrollzeit}\\
+von: 13:21\\
+bis: 19:30
+}
+&
+\parbox[c][\rowheight][t]{6.5cm}{%
+\vspace{2mm}
+\textbf{Kontrollfrage:}\\
+Wann wurde das Kriegerdenkmal\\
+eingerichtet?
+}
+\\
+\hline
+
+% Row 2 (Lower card) - height 2.833cm
+\parbox[c][\rowheight][t]{6.5cm}{%
+\vspace{2mm}
+\textbf{Nr. 2:} Km 57 -- „Nationalpark-Tor" im\\
+alten Bahnhofsgebäude, Heimbach\\
+\\
+\textbf{Kontrollzeit}\\
+von: 9:11\\
+bis: 12:21
+}
+&
+\parbox[c][\rowheight][c]{6.5cm}{%
+% Empty for stamps
+}
+&
+\parbox[c][\rowheight][t]{6.5cm}{%
+\vspace{2mm}
+\textbf{Nr. 5:} Km 214 - Unisport\\
+Nachtigallenweg 86, Bonn\\
+\\
+\textbf{Kontrollzeit}\\
+von: 13:23\\
+bis: 21:00
+}
+&
+\parbox[c][\rowheight][c]{6.5cm}{%
+% Empty
+}
+\\
+\hline
+
+% Row 3 (Lower card) - height 2.833cm
+\parbox[c][\rowheight][t]{6.5cm}{%
+\vspace{2mm}
+\textbf{Nr. 3:} Km 100 - Friterie „Au Petit\\
+Creux" oder Total-Tankstelle, Ecke Rue\\
+de Botrange/Rue de Charmilles, Waimes\\
+\textbf{Kontrollzeit}\\
+von: 11:26\\
+bis: 15:10
+}
+&
+\parbox[c][\rowheight][c]{6.5cm}{%
+% Empty for stamps
+}
+&
+\parbox[c][\rowheight][c]{6.5cm}{%
+% Empty
+}
+&
+\parbox[c][\rowheight][c]{6.5cm}{%
+% Empty
+}
+\\
+\hline
+\end{tabular}
+
+\end{document}
diff --git a/brevetkarte.tex b/brevetkarte.tex
new file mode 100644
index 0000000..70a2ef3
--- /dev/null
+++ b/brevetkarte.tex
@@ -0,0 +1,138 @@
+\documentclass[a4paper,10pt,landscape]{article}
+\usepackage[utf8]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage[landscape,top=0.8cm,bottom=0.8cm,left=0.8cm,right=0.8cm]{geometry}
+\usepackage{graphicx}
+\usepackage{xcolor}
+\usepackage{tikz}
+\usepackage{helvet}
+\usepackage{hyperref}
+\usepackage{enumitem}
+
+% Set sans-serif font as default
+\renewcommand{\familydefault}{\sfdefault}
+
+% Define colors
+\definecolor{headerblack}{RGB}{0,0,0}
+
+% Configure hyperlinks to be black
+\hypersetup{
+ colorlinks=true,
+ linkcolor=black,
+ urlcolor=black,
+ citecolor=black
+}
+
+\setlength{\parindent}{0pt}
+\pagestyle{empty}
+
+% Command to create one brevet card
+\newcommand{\brevetcard}{%
+\noindent
+\begin{tikzpicture}[x=1cm,y=1cm]
+
+% Black vertical separator lines (drawn first, extend through headers)
+\draw[black,line width=0.5pt] (6.9,-7.2) -- (6.9,1.3);
+\draw[black,line width=0.5pt] (13.8,-7.2) -- (13.8,1.3);
+\draw[black,line width=0.5pt] (20.7,-7.2) -- (20.7,1.3);
+
+% Black header boxes (drawn on top)
+\fill[headerblack] (0,0) rectangle (6.9,1.3);
+\node[white,align=center,font=\tiny,text width=6.6cm] at (3.45,0.65) {
+ Jeder Teilnehmer muss diese Brevetkarte zu jeder Zeit\\
+ mit sich führen und an den Kontrollen abstempeln lassen\\
+ bzw. Fotos erstellen.\\
+ \textbf{Ohne Kontrollzeiten und Zielzeit keine Wertung!}
+};
+
+\fill[headerblack] (6.9,0) rectangle (13.8,1.3);
+\node[white,font=\Large] at (10.35,0.65) {HOMOLOGATION};
+
+\fill[headerblack] (13.8,0) rectangle (20.7,1.3);
+\node[white,font=\Large] at (17.25,0.65) {TEILNEHMER/-IN};
+
+\fill[headerblack] (20.7,0) rectangle (27.6,1.3);
+\node[white,align=center,font=\normalsize] at (24.15,0.75) {BREVET DES RANDONNEURS};
+\node[white,font=\Large] at (24.15,0.35) {MONDIAUX};
+
+% Column 1 - Rules (left section)
+\node[anchor=north west,text width=6.6cm,font=\small,align=left] at (0.2,-0.3) {
+ \textbf{Es gelten die Regeln von}\\
+ \textbf{Randonneur Mondiaux}\\
+ \textbf{insbesondere:}
+ \begin{itemize}[leftmargin=0.4cm,itemsep=1pt,topsep=2pt,parsep=0pt]
+ \item Einhaltung der StVO
+ \item Beleuchtung und Sicherheitsweste/-Gurt
+ \item keine Abkürzungen
+ \item keine Begleitfahrzeuge
+ \item Rücksicht auf Teilnehmer und Umwelt
+ \item Rücksicht in den Kontrollen
+ \end{itemize}
+ \hspace{0.3cm}$\Rightarrow$ \textbf{\underline{Bei Verstoß keine Wertung!}}\\[0.3cm]
+ -
+};
+
+\node[anchor=south west,text width=6.6cm,font=\small,align=left] at (0.2,-7.0) {
+ \textbf{AUDAX RANDONNEURS ALLEMAGNE E.V.}\\
+ \href{http://www.audax-randonneure.de}{www.audax-randonneure.de}\\
+ - gegründet 1992 in Hamburg -
+};
+
+% Column 2 - Homologation (middle-left section)
+\node[anchor=north,text width=6.6cm,font=\small,align=center] at (10.35,-0.5) {
+ Der Randonnée wurde beendet in:\\[0.6cm]
+ \makebox[2cm]{\dotfill}h\makebox[2cm]{\dotfill}min
+};
+
+\node[anchor=center,font=\Large] at (10.35,-4.0) {
+ HOMOLOGATION
+};
+
+\node[anchor=south,text width=6.6cm,font=\small,align=center] at (10.35,-6.8) {
+ Brevet N° \makebox[5cm]{\dotfill}
+};
+
+% Column 3 - Participant Info (middle-right section)
+\node[anchor=north west,text width=6.6cm,font=\small,align=left] at (14.0,-0.5) {
+ Name:\\[0.4cm]
+ Straße:\\[0.4cm]
+ PLZ/Ort:\\[0.4cm]
+ Land:\\[0.4cm]
+ Medaille:\\[0.6cm]
+ Startzeit: 8:30
+};
+
+% Column 4 - Event Info (right section)
+\node[anchor=north,text width=6.6cm,align=center] at (24.15,-0.4) {
+ \includegraphics[width=5.5cm]{cyclist-logo.png}
+};
+
+\node[anchor=north,text width=6.6cm,font=\small,align=center] at (24.15,-2.2) {
+ \textbf{Auf eine Pommes nach Belgien}\\
+ Randonnée über \textbf{200} km\\
+ am \textbf{20. September 2025}\\
+ mit Start in \textbf{Bonn, Uni-Sportgelände}\\
+ von \textbf{ARA Rheinland}\\
+ N° ACP du Club \textbf{111011}
+};
+
+\node[anchor=south,text width=6.6cm,font=\scriptsize,align=center] at (24.15,-7.0) {
+ CONTRÔLÉE ET HOMOLOGUÉE EXCLUSIVEMENT PAR\\
+ \href{http://www.audax-club-parisien.com}{www.audax-club-parisien.com}\\
+ - Société fondée en 1904 -
+};
+
+\end{tikzpicture}
+}
+
+\begin{document}
+
+% First brevet card
+\brevetcard
+
+\vspace{0.8cm}
+
+% Second brevet card (identical)
+\brevetcard
+
+\end{document}
diff --git a/cyclist-logo.png b/cyclist-logo.png
new file mode 100644
index 0000000..f3b0c43
Binary files /dev/null and b/cyclist-logo.png differ