|
import argparse |
|
import csv |
|
import random |
|
import re |
|
import string |
|
from unicodedata import normalize |
|
from pathlib import Path |
|
|
|
|
|
def slug(text): |
|
""" |
|
>>> slug(' Álvaro ') |
|
'alvaro' |
|
>>> slug('E-Mail') |
|
'e_mail' |
|
>>> slug(' ?#$ E-----Mail!!@?') |
|
'e_mail' |
|
""" |
|
text = normalize("NFKD", text).encode("ascii", errors="ignore").decode("ascii").strip().lower() |
|
allowed = string.ascii_letters + string.digits + "_" |
|
escaped = "".join("_" if char not in allowed else char for char in text) |
|
clean = re.sub("_+", "_", escaped) |
|
if clean[0] == "_": |
|
clean = clean[1:] |
|
if clean[-1] == "_": |
|
clean = clean[:-1] |
|
return clean |
|
|
|
def plural(n): |
|
return 's' if n != 1 else '' |
|
|
|
|
|
def _parser(): |
|
parser = argparse.ArgumentParser( |
|
prog="sorteio", |
|
description="Lê participantes de CSV e executa N sorteios, salvando o resultado", |
|
) |
|
parser.add_argument("csv_participantes", type=Path) |
|
parser.add_argument("sorteios", type=int, help="Quantidade de sorteios a serem feitos") |
|
parser.add_argument("csv_resultado", type=Path) |
|
return parser |
|
|
|
|
|
def main(args): |
|
csv_participantes = args.csv_participantes |
|
csv_resultado = args.csv_resultado |
|
sorteios = args.sorteios |
|
|
|
# Lê CSV de participantes |
|
participantes = {} |
|
with csv_participantes.open() as fobj: |
|
reader = csv.reader(fobj) |
|
# Cria um "slug" do cabeçalho |
|
header = [slug(value.splitlines()[0]) for value in next(reader)] |
|
max_column_size = max(len(key) for key in header) |
|
if "id" in header: |
|
parser.exit( |
|
status=100, |
|
message="O CSV não pode possuir uma coluna 'id', pois essa será criada para o sorteio.\n", |
|
) |
|
seq_id = 1 |
|
for values in reader: |
|
row = {"id": seq_id, **dict(zip(header, values))} |
|
participantes[row["id"]] = row |
|
seq_id += 1 |
|
total_lidos = len(participantes) |
|
print(f"Total de {total_lidos} registro{plural(total_lidos)} lido{plural(total_lidos)} do CSV.") |
|
|
|
# Filtra apenas pelos que não têm o livro |
|
participantes = { |
|
id_: participante for id_, participante in participantes.items() if participante["ja_possui_o_livro"] == "Não" |
|
} |
|
total_depois = len(participantes) |
|
if total_depois != total_lidos: |
|
dif = total_lidos - total_depois |
|
print(f"Removido{plural(dif)} {dif} participante{plural(dif)} que já {'têm' if dif != 1 else 'tem'} o livro.") |
|
|
|
# Faz os sorteios |
|
print("Pressione ENTER para continuar") |
|
input() |
|
print( |
|
f"Iniciando {sorteios} sorteio{plural(sorteios)} " |
|
f"para {total_depois} participante{plural(total_depois)}.\n" |
|
) |
|
with csv_resultado.open(mode="w") as fobj: |
|
writer = None |
|
for sorteio in range(1, sorteios + 1): |
|
id_sorteado = random.choice(list(participantes.keys())) |
|
participante = participantes.pop(id_sorteado) |
|
resultado = {"sorteio": sorteio, **participante} |
|
if writer is None: |
|
writer = csv.DictWriter(fobj, fieldnames=list(resultado.keys())) |
|
writer.writeheader() |
|
writer.writerow(resultado) |
|
print(f"- Sorteio {sorteio}:") |
|
for key, value in participante.items(): |
|
if key in ("email", "e_mail", "email_address", "telefone", "telefone_com_ddd", "ja_possui_o_livro"): |
|
# Evita mostrar dados sensíveis |
|
continue |
|
print(f" {key.rjust(max_column_size)}: {value}") |
|
print() |
|
|
|
|
|
if __name__ == "__main__": |
|
import sys |
|
|
|
parser = _parser() |
|
args = parser.parse_args() |
|
sys.exit(main(args)) |