script per stampa badge last minute

This commit is contained in:
2026-05-05 17:30:15 +02:00
parent 65b63e1663
commit cb197c1c6f
4 changed files with 216 additions and 1 deletions
+1
View File
@@ -174,3 +174,4 @@ cython_debug/
# PyPI configuration file
.pypirc
*.pdf
+62 -1
View File
@@ -1,3 +1,64 @@
# grafica-badge-itdevcon
Script python per la creazione delle grafiche dei badge vuoti di itdevcon (per i partecipanti dell'ultimo minuto)
Script python per la creazione delle grafiche dei badge vuoti di itdevcon (per i partecipanti dell'ultimo minuto)
## Setup ambiente
Prerequisito: [uv](https://docs.astral.sh/uv/getting-started/installation/) installato.
```bash
# Crea e attiva il virtual environment
uv venv
# Installa le dipendenze da requirements.txt
uv pip install -r requirements.txt
```
Per attivare manualmente il virtual environment:
- **Windows (PowerShell):** `.venv\Scripts\Activate.ps1`
- **Windows (CMD):** `.venv\Scripts\activate.bat`
- **Linux/macOS:** `source .venv/bin/activate`
## Esecuzione
Con uv (senza attivare manualmente il venv):
```bash
uv run genera_badge.py
```
Oppure, con il virtual environment attivo:
```bash
python genera_badge.py
```
L'output è un file PDF (`badge_qr.pdf`) con i badge pronti per la stampa.
## Cosa fa lo script
`genera_badge.py` genera badge in formato PDF per i partecipanti dell'evento itdevcon.
Per ogni partecipante crea un badge di **9x5 cm** contenente:
- **Nome** e **azienda** (centrati, font Helvetica-Bold 18pt)
- **QR code** con il link alla pagina di voto live (`https://live.itdevcon.it/web/vote/<id>`)
- **Angoli di ritaglio** (segni a "L" sui 4 angoli per facilitare il taglio manuale)
Il layout è ottimizzato per la stampa su **A4 landscape**: ogni pagina ospita una griglia di **2 righe x 3 colonne** (6 badge per pagina). Questa disposizione è stata scelta per evitare la zona laterale del foglio adesivo pieghevole, che non è stampabile, usando solo le aree "buone" del foglio.
Il file di output predefinito è `badge_qr.pdf`.
### Personalizzazione
I dati dei partecipanti vanno inseriti direttamente nell'array `partecipanti` all'interno dello script (`genera_badge.py`, riga 12). Ogni entry è un dizionario con chiavi `id`, `nome` e opzionale `azienda`.
Esempio:
```python
partecipanti = [
{"id": "ABC123", "nome": "Mario Rossi", "azienda": "ItDevCon Srl"},
{"id": "DEF456", "nome": "Anna Bianchi", "azienda": ""},
]
```
+151
View File
@@ -0,0 +1,151 @@
import qrcode
from reportlab.lib.pagesizes import A4, landscape
from reportlab.lib.units import cm
from reportlab.lib.utils import ImageReader
from reportlab.pdfgen import canvas
from PIL import Image
import io
import os
# --- CONFIGURAZIONE ---
partecipanti = [
# {"id": "ABC123", "nome": "Mario Rossi Mrio Rossi Mario R", "azienda": "ItDevCon Srl"},
# {"id": "f6d8a77b7348f111", "nome": "Pietro Angelo Polito", "azienda": "Tecnofarma Srl"},
# {"id": "f0d8a77b7348f111", "nome": "Helena Giliberti", "azienda": ""},
# {"id": "f3d8a77b7348f111", "nome": "Simone Ercolani", "azienda": "Itaca"},
# {"id": "f2d8a77b7348f111", "nome": "Emanuele Malvatani", "azienda": "Itaca"},
# {"id": "f1d8a77b7348f111", "nome": "Lorenzo Maria Soricetti", "azienda": "Itaca"},
# {"id": "f4d8a77b7348f111", "nome": "Luca Malvatani", "azienda": "Itaca"},
{"id": "f5d8a77b7348f111", "nome": "Alessio Cimadamore", "azienda": "Itaca"},
# Aggiungi quanti partecipanti vuoi
]
base_url = "https://live.itdevcon.it/web/vote/"
output_pdf = "badge_qr.pdf"
# Dimensioni singolo badge (cm)
badge_w = 9 * cm
badge_h = 5 * cm
# Margini pagina A4 landscape
margin_x = 1.0 * cm
margin_y = 1.5 * cm
# Layout griglia su A4 landscape
rows_per_page = 2
cols_per_page = 3
# Font
font_name = "Helvetica-Bold"
font_size = 18
font_azienda = "Helvetica"
font_size_azienda = 12
# QR code
qr_width = 3.2 * cm # larghezza/altezza del QR nel PDF
# Colore branding
color_brand = "#040073"
color_brand_light = "#4A6DAD"
def create_qr_image(data, size=200):
"""Genera un'immagine QR code in memoria come BytesIO PNG."""
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_M,
box_size=10,
border=1,
)
qr.add_data(data)
qr.make(fit=True)
img = qr.make_image(fill_color=color_brand, back_color="white")
img = img.convert("RGB")
img = img.resize((size, size), Image.LANCZOS)
img_bytes = io.BytesIO()
img.save(img_bytes, format="PNG")
img_bytes.seek(0)
return img_bytes
def draw_badge(c, x, y, id_partecipante, nome, azienda):
"""Disegna un singolo badge 9x5 cm con angolo in basso a sinistra a (x, y)."""
nome = nome[:26]
azienda = azienda[:26]
link = f"{base_url}{id_partecipante}"
# Angoli per facilitare il ritaglio (L di 0.5 cm per angolo)
c.setStrokeColorRGB(0, 0, 0)
c.setLineWidth(0.5)
corner = 0.5 * cm
# Angolo basso-sinistra
c.line(x, y, x + corner, y)
c.line(x, y, x, y + corner)
# Angolo basso-destra
c.line(x + badge_w - corner, y, x + badge_w, y)
c.line(x + badge_w, y, x + badge_w, y + corner)
# Angolo alto-sinistra
c.line(x, y + badge_h - corner, x, y + badge_h)
c.line(x, y + badge_h, x + corner, y + badge_h)
# Angolo alto-destra
c.line(x + badge_w - corner, y + badge_h, x + badge_w, y + badge_h)
c.line(x + badge_w, y + badge_h - corner, x + badge_w, y + badge_h)
# Nome centrato nella parte superiore
c.setFillColor(color_brand)
c.setFont(font_name, font_size)
text_width = c.stringWidth(nome, font_name, font_size)
text_x = x + (badge_w - text_width) / 2
text_y = y + badge_h - 0.7 * cm
c.drawString(text_x, text_y, nome)
# Azienda centrata subito sotto il nome (font più fine)
c.setFillColor(color_brand_light)
c.setFont(font_azienda, font_size_azienda)
text_width = c.stringWidth(azienda, font_azienda, font_size_azienda)
text_x = x + (badge_w - text_width) / 2
text_y_azienda = text_y - 0.6 * cm
c.drawString(text_x, text_y_azienda, azienda)
# QR code centrato subito sotto l'azienda
qr_bytes = create_qr_image(link, size=200)
qr_img = ImageReader(qr_bytes)
qr_x = x + (badge_w - qr_width) / 2
qr_y = text_y_azienda - qr_width - 0.3 * cm
c.drawImage(qr_img, qr_x, qr_y, width=qr_width, height=qr_width)
def generate_pdf():
c = canvas.Canvas(output_pdf, pagesize=landscape(A4))
page_w, page_h = landscape(A4)
# Spazio fisso tra badge per facilitare il ritaglio
gap = 0.2 * cm
per_page = rows_per_page * cols_per_page
for idx, p in enumerate(partecipanti):
if idx > 0 and idx % per_page == 0:
c.showPage()
pos_in_page = idx % per_page
col = pos_in_page % cols_per_page
row = pos_in_page // cols_per_page
x = page_w - margin_x - badge_w - col * (badge_w + gap)
y = page_h - margin_y - (row + 1) * badge_h - row * gap
draw_badge(c, x, y, p["id"], p["nome"], p.get("azienda", ""))
c.save()
print(f"PDF generato: {os.path.abspath(output_pdf)}")
print(f"Totale badge: {len(partecipanti)}")
if __name__ == "__main__":
generate_pdf()
+2
View File
@@ -0,0 +1,2 @@
qrcode[pil]
reportlab