diff --git a/repartir_taches/config.py b/repartir_taches/config.py index bcb5f57..1935b5d 100644 --- a/repartir_taches/config.py +++ b/repartir_taches/config.py @@ -90,7 +90,7 @@ class Config: descr=task["descr"].format(**self.env), notes=task.get("notes", ""), time=task.get("heure", ""), - nb_groups=int(task.get("nb_groups", 1)), + nb_groups=int(task.get("nb_groupes", 1)), ) def _load_people(self) -> None: diff --git a/repartir_taches/entrypoint.py b/repartir_taches/entrypoint.py index 5958c84..70619ec 100644 --- a/repartir_taches/entrypoint.py +++ b/repartir_taches/entrypoint.py @@ -1,8 +1,11 @@ import argparse import typing as t import random +from pathlib import Path +import jinja2 as j2 from .config import Task, Category, Config +from . import util def constituer_groupes(choristes: list[str]) -> list[list[str]]: @@ -48,8 +51,8 @@ def assigner_taches(task: Category | Task, group_count: int, cur_group: int = 0) return cur_group -def export_short(config: Config, groupes: list[list[str]]) -> str: - """Exporte la liste des tâches au format court (pour vérification)""" +def export_short_md(config: Config, groupes: list[list[str]]) -> str: + """Exporte la liste des tâches au format Markdown court (pour vérification)""" def export_taskcat(grp: Task | Category) -> str: if isinstance(grp, Task): @@ -77,12 +80,31 @@ def export_short(config: Config, groupes: list[list[str]]) -> str: def export_latex(config: Config, groupes: list[list[str]]) -> str: """Exporter la liste des tâches en LaTeX (à insérer dans un template)""" + j2_env = util.j2_environment() + template = j2_env.get_template("repartition.tex.j2") + env = { + "groupes": {g_id: grp for g_id, grp in enumerate(groupes)}, + "taches": config.taches.tasks, + } + return template.render(**env) def main(): parser = argparse.ArgumentParser("Répartition des tâches") parser.add_argument("taches", help="Fichier yaml contenant les tâches") parser.add_argument("choristes", help="Fichier CSV contenant les choristes") + parser.add_argument("--to-tex", help="Exporter vers un fichier LaTeX") + parser.add_argument( + "--to-short-md", + help="Exporter vers un fichier Markdown (pour vérification uniquement)", + ) args = parser.parse_args() config = Config(args.taches, args.choristes) + groupes = constituer_groupes(config.choristes) + assigner_taches(config.taches, len(groupes)) + + if args.to_tex: + util.write_to_file(args.to_tex, export_latex(config, groupes)) + if args.to_short_md: + util.write_to_file(args.to_short_md, export_short_md(config, groupes)) diff --git a/repartir_taches/templates/category.tex.j2 b/repartir_taches/templates/category.tex.j2 new file mode 100644 index 0000000..6b6e187 --- /dev/null +++ b/repartir_taches/templates/category.tex.j2 @@ -0,0 +1,9 @@ +{% if cat|attr('depth') %} + \{%- for i in range(cat.depth-1) -%}sub{%- endfor -%}category{ {{- cat.name -}} }{ {{- cat.time -}} } + + {% for cat in cat.tasks %} + {% include 'category.tex.j2' %} + {% endfor %} +{% else %} + {% include 'tache.tex.j2' %} +{% endif %} diff --git a/repartir_taches/templates/groupe.tex.j2 b/repartir_taches/templates/groupe.tex.j2 new file mode 100644 index 0000000..d1e59c0 --- /dev/null +++ b/repartir_taches/templates/groupe.tex.j2 @@ -0,0 +1 @@ +\groupe{ {{- g_id + 1 -}} } &--- {{ ', '.join(groupes[g_id]) }} \\ diff --git a/repartir_taches/templates/repartition.tex.j2 b/repartir_taches/templates/repartition.tex.j2 new file mode 100644 index 0000000..f028558 --- /dev/null +++ b/repartir_taches/templates/repartition.tex.j2 @@ -0,0 +1,45 @@ +{% raw %} +\documentclass[a4paper]{article} + +\usepackage[margin=1.5cm]{geometry} +\usepackage[dvipsnames]{xcolor} +\usepackage[T1]{fontenc} +\usepackage[fontsize=14pt]{fontsize} +\usepackage{mdframed} + +\title{\vspace{-1.5cm}Répartition des tâches} +\author{} +\date{\vspace{-2.5cm}} + +\newcommand{\groupe}[1]{#1} +\newcommand{\heure}[1]{#1} + +\newcommand{\category}[2]{ + \vspace{1em} + \begin{center} + \textbf{\Large#1} + \end{center}\hfill #2\\ + \vspace{1em} +} +\newcommand{\subcategory}[2]{ + \vspace{1em}\hspace{2em}\textbf{\large#1}\hfill #2\\ + \vspace{1em} +} +{% endraw %} + +\begin{document} + \maketitle + + \section*{Groupes} + + \begin{tabular}{r l} + {% for g_id, _ in groupes.items() %} + {% include 'groupe.tex.j2' %} + {%- endfor %} + \end{tabular} + + {% for cat in taches -%} + {% include 'category.tex.j2' %} + {% endfor %} + +\end{document} diff --git a/repartir_taches/templates/tache.tex.j2 b/repartir_taches/templates/tache.tex.j2 new file mode 100644 index 0000000..a8a1f40 --- /dev/null +++ b/repartir_taches/templates/tache.tex.j2 @@ -0,0 +1,13 @@ +\vbox{ +\noindent\textbf{ {{- cat.name -}} }{% if cat.time -%} + \hfill\heure{ {{- cat.time -}} } +{%- endif %} \\ +{{ cat.descr|md_format|escape_latex }} \\ +{% if cat.notes %}\textit{ {{- cat.notes -}} } \\ +{% endif -%} +\begin{tabular}{r l} +{% for g_id in cat.assigned %} {% include 'groupe.tex.j2' %} +{%- endfor -%} +\end{tabular} +} +\vspace{1.5em} diff --git a/repartir_taches/util.py b/repartir_taches/util.py index cb8d996..6feb241 100644 --- a/repartir_taches/util.py +++ b/repartir_taches/util.py @@ -1,5 +1,8 @@ """ Utility functions and classes """ +import jinja2 as j2 +import re + def levenshtein_distance(s1, s2): """Compute the Levenshtein distance (edit distance) between two strings @@ -57,3 +60,38 @@ class UnionFind: def group_size(self, elt: int) -> int: """Get the number of elements in the component of :elt:""" return self._group_size[self.root(elt)] + + +def write_to_file(path: str, content: str) -> None: + """Write :content: to the file at :path:, truncating it. Writes to stdout instead + if :path: is `-`.""" + if path == "-": + print(content) + else: + with open(path, "w") as handle: + handle.write(content) + + +_MD_RE_ITAL = re.compile(r"\*(.+?)\*") +_MD_RE_BOLD = re.compile(r"\*\*(.+?)\*\*") + + +def md_format(val: str) -> str: + val = _MD_RE_BOLD.sub(r"\\textbf{\1}", val) + val = _MD_RE_ITAL.sub(r"\\textit{\1}", val) + return val + + +_TEX_NBSP = re.compile(r" ([?!])") + + +def escape_latex(val: str) -> str: + val = _TEX_NBSP.sub(r"~\1", val) + return val.replace("&", r"\&") + + +def j2_environment() -> j2.Environment: + env = j2.Environment(loader=j2.PackageLoader("repartir_taches")) + env.filters["escape_latex"] = escape_latex + env.filters["md_format"] = md_format + return env